From: Josh Durgin Date: Tue, 4 Jul 2017 01:06:23 +0000 (-0400) Subject: osd_types, PGLog: encode missing based on features X-Git-Tag: v12.1.2~220^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a51d5fd9a11e852361df5e3e90d04710a8f19cb4;p=ceph.git osd_types, PGLog: encode missing based on features Store whether the missing set should contain deletes, so that persisted versions can be rebuilt if needed. Make missing_item versioned, since it's persisted by the pg_log as an individual omap value. Signed-off-by: Josh Durgin --- diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 168ed276d03f..3bc6db4d9e45 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -1738,12 +1738,18 @@ void PG::activate(ObjectStore::Transaction& t, if (m && pi.last_backfill != hobject_t()) { for (list::iterator p = m->log.log.begin(); p != m->log.log.end(); - ++p) + ++p) { if (p->soid <= pi.last_backfill && - !p->is_error()) - pm.add_next_event(*p); + !p->is_error()) { + if (perform_deletes_during_peering() && p->is_delete()) { + pm.rm(p->soid, p->version); + } else { + pm.add_next_event(*p); + } + } + } } - + if (m) { dout(10) << "activate peer osd." << peer << " sending " << m->log << dendl; //m->log.print(cout); diff --git a/src/osd/PGLog.cc b/src/osd/PGLog.cc index 9830e5b05b19..99bbedf6ef61 100644 --- a/src/osd/PGLog.cc +++ b/src/osd/PGLog.cc @@ -458,6 +458,7 @@ void PGLog::write_log_and_missing( !touched_log, require_rollback, clear_divergent_priors, + &rebuilt_missing_with_deletes, (pg_log_debug ? &log_keys_debug : 0)); undirty(); } else { @@ -487,7 +488,8 @@ void PGLog::write_log_and_missing( const coll_t& coll, const ghobject_t &log_oid, const pg_missing_tracker_t &missing, - bool require_rollback) + bool require_rollback, + bool *rebuilt_missing_with_deletes) { _write_log_and_missing( t, km, log, coll, log_oid, @@ -496,7 +498,7 @@ void PGLog::write_log_and_missing( eversion_t(), set(), missing, - true, require_rollback, false, 0); + true, require_rollback, false, rebuilt_missing_with_deletes, 0); } void PGLog::_write_log_and_missing_wo_missing( @@ -602,6 +604,7 @@ void PGLog::_write_log_and_missing( bool touch_log, bool require_rollback, bool clear_divergent_priors, + bool *rebuilt_missing_with_deletes, // in/out param set *log_keys_debug ) { set to_remove; @@ -664,6 +667,12 @@ void PGLog::_write_log_and_missing( //dout(10) << "write_log_and_missing: writing divergent_priors" << dendl; to_remove.insert("divergent_priors"); } + // since we encode individual missing items instead of a whole + // missing set, we need another key to store this bit of state + if (*rebuilt_missing_with_deletes) { + (*km)["may_include_deletes_in_missing"] = bufferlist(); + *rebuilt_missing_with_deletes = false; + } missing.get_changed( [&](const hobject_t &obj) { string key = string("missing/") + obj.to_str(); @@ -671,8 +680,8 @@ void PGLog::_write_log_and_missing( if (!missing.is_missing(obj, &item)) { to_remove.insert(key); } else { - ::encode(obj, (*km)[key]); - item.encode_with_flags((*km)[key]); + uint64_t features = missing.may_include_deletes ? CEPH_FEATURE_OSD_RECOVERY_DELETES : 0; + ::encode(make_pair(obj, item), (*km)[key], features); } }); if (require_rollback) { diff --git a/src/osd/PGLog.h b/src/osd/PGLog.h index 0d484e335e60..25a794605c14 100644 --- a/src/osd/PGLog.h +++ b/src/osd/PGLog.h @@ -497,6 +497,7 @@ protected: /// Log is clean on [dirty_to, dirty_from) bool touched_log; bool clear_divergent_priors; + bool rebuilt_missing_with_deletes = false; void mark_dirty_to(eversion_t to) { if (to > dirty_to) @@ -517,7 +518,8 @@ public: (dirty_from != eversion_t::max()) || (writeout_from != eversion_t::max()) || !(trimmed.empty()) || - !missing.is_clean(); + !missing.is_clean() || + rebuilt_missing_with_deletes; } void mark_log_for_rewrite() { mark_dirty_to(eversion_t::max()); @@ -805,7 +807,8 @@ protected: assert(objiter->second->version > last_divergent_update); // ensure missing has been updated appropriately - if (objiter->second->is_update() || objiter->second->is_delete()) { + if (objiter->second->is_update() || + (missing.may_include_deletes && objiter->second->is_delete())) { assert(missing.is_missing(hoid) && missing.get_items().at(hoid).need == objiter->second->version); } else { @@ -1013,7 +1016,23 @@ public: } if (p->soid <= last_backfill && !p->is_error()) { - missing.add_next_event(*p); + if (missing.may_include_deletes) { + missing.add_next_event(*p); + } else { + if (p->is_delete()) { + missing.rm(p->soid, p->version); + } else { + missing.add_next_event(*p); + } + if (rollbacker) { + // hack to match PG::mark_all_unfound_lost + if (maintain_rollback && p->is_lost_delete() && p->can_rollback()) { + rollbacker->try_stash(p->soid, p->version.version); + } else if (p->is_delete()) { + rollbacker->remove(p->soid); + } + } + } } } return invalidate_stats; @@ -1070,7 +1089,8 @@ public: const coll_t& coll, const ghobject_t &log_oid, const pg_missing_tracker_t &missing, - bool require_rollback); + bool require_rollback, + bool *rebuilt_missing_set_with_deletes); static void _write_log_and_missing_wo_missing( ObjectStore::Transaction& t, @@ -1101,6 +1121,7 @@ public: bool touch_log, bool require_rollback, bool clear_divergent_priors, + bool *rebuilt_missing_with_deletes, set *log_keys_debug ); @@ -1149,6 +1170,7 @@ public: ObjectMap::ObjectMapIterator p = store->get_omap_iterator(log_coll, log_oid); map divergent_priors; bool has_divergent_priors = false; + missing.may_include_deletes = false; list entries; if (p) { for (p->seek_to_first(); p->valid() ; p->next(false)) { @@ -1167,11 +1189,16 @@ public: ::decode(on_disk_can_rollback_to, bp); } else if (p->key() == "rollback_info_trimmed_to") { ::decode(on_disk_rollback_info_trimmed_to, bp); + } else if (p->key() == "may_include_deletes_in_missing") { + missing.may_include_deletes = true; } else if (p->key().substr(0, 7) == string("missing")) { hobject_t oid; pg_missing_item item; ::decode(oid, bp); - item.decode_with_flags(bp); + ::decode(item, bp); + if (item.is_delete()) { + assert(missing.may_include_deletes); + } missing.add(oid, item.need, item.have, item.is_delete()); } else { pg_log_entry_t e; @@ -1216,6 +1243,9 @@ public: if (did.count(i->soid)) continue; did.insert(i->soid); + if (!missing.may_include_deletes && i->is_delete()) + continue; + bufferlist bv; int r = store->getattr( pg_coll, diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index 8913f12b9cd9..3dd61fa5e0ff 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -4262,6 +4262,7 @@ ostream& operator<<(ostream& out, const pg_missing_item& i) out << i.need; if (i.have != eversion_t()) out << "(" << i.have << ")"; + out << " flags = " << i.flag_str(); return out; } diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 6bc75e3dbded..1a2dd305b19e 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -3596,13 +3596,37 @@ struct pg_missing_item { set_delete(is_delete); } - void encode(bufferlist& bl) const { - ::encode(need, bl); - ::encode(have, bl); + void encode(bufferlist& bl, uint64_t features) const { + if (HAVE_FEATURE(features, OSD_RECOVERY_DELETES)) { + // encoding a zeroed eversion_t to differentiate between this and + // legacy unversioned encoding - a need value of 0'0 is not + // possible. This can be replaced with the legacy encoding + // macros post-luminous. + eversion_t e; + ::encode(e, bl); + ::encode(need, bl); + ::encode(have, bl); + ::encode(static_cast(flags), bl); + } else { + // legacy unversioned encoding + ::encode(need, bl); + ::encode(have, bl); + } } void decode(bufferlist::iterator& bl) { - ::decode(need, bl); - ::decode(have, bl); + eversion_t e; + ::decode(e, bl); + if (e != eversion_t()) { + // legacy encoding, this is the need value + need = e; + ::decode(have, bl); + } else { + ::decode(need, bl); + ::decode(have, bl); + uint8_t f; + ::decode(f, bl); + flags = static_cast(f); + } } void set_delete(bool is_delete) { @@ -3613,26 +3637,18 @@ struct pg_missing_item { return (flags & FLAG_DELETE) == FLAG_DELETE; } - void encode_with_flags(bufferlist& bl) const { - encode(bl); - ::encode(static_cast(flags), bl); - } - - void decode_with_flags(bufferlist::iterator& bl) { - decode(bl); - // no versioning on this, but it's stored in a single omap value, - // so just check for the end of the bufferlist - if (!bl.end()) { - uint8_t f; - ::decode(f, bl); - flags = static_cast(f); + string flag_str() const { + if (flags == FLAG_NONE) { + return "none"; + } else { + return "delete"; } } void dump(Formatter *f) const { f->dump_stream("need") << need; f->dump_stream("have") << have; - f->dump_stream("flags") << (flags == FLAG_NONE ? "none" : "delete"); + f->dump_stream("flags") << flag_str(); } static void generate_test_instances(list& o) { o.push_back(new pg_missing_item); @@ -3651,7 +3667,7 @@ struct pg_missing_item { return !(*this == rhs); } }; -WRITE_CLASS_ENCODER(pg_missing_item) +WRITE_CLASS_ENCODER_FEATURES(pg_missing_item) ostream& operator<<(ostream& out, const pg_missing_item &item); class pg_missing_const_i { @@ -3659,6 +3675,7 @@ public: virtual const map & get_items() const = 0; virtual const map &get_rmissing() const = 0; + virtual bool get_may_include_deletes() const = 0; virtual unsigned int num_missing() const = 0; virtual bool have_missing() const = 0; virtual bool is_missing(const hobject_t& oid, pg_missing_item *out = nullptr) const = 0; @@ -3714,16 +3731,22 @@ public: pg_missing_set(const missing_type &m) { missing = m.get_items(); rmissing = m.get_rmissing(); + may_include_deletes = m.get_may_include_deletes(); for (auto &&i: missing) tracker.changed(i.first); } + bool may_include_deletes = false; + const map &get_items() const override { return missing; } const map &get_rmissing() const override { return rmissing; } + bool get_may_include_deletes() const override { + return may_include_deletes; + } unsigned int num_missing() const override { return missing.size(); } @@ -3851,6 +3874,7 @@ public: pg_t child_pgid, unsigned split_bits, pg_missing_set *omissing) { + omissing->may_include_deletes = may_include_deletes; unsigned mask = ~((~0)<::iterator i = missing.begin(); i != missing.end(); @@ -3874,17 +3898,8 @@ public: void encode(bufferlist &bl) const { ENCODE_START(4, 2, bl); - ::encode(missing, bl); - // since pg_missing_item was not versioned, we encode the new flags - // field here explicitly - map missing_flags; - for (const auto &p : missing) { - if (p.second.flags != pg_missing_item::FLAG_NONE) { - missing_flags.insert(make_pair(p.first, - static_cast(p.second.flags))); - } - } - ::encode(missing_flags, bl); + ::encode(missing, bl, may_include_deletes ? CEPH_FEATURE_OSD_RECOVERY_DELETES : 0); + ::encode(may_include_deletes, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator &bl, int64_t pool = -1) { @@ -3893,12 +3908,7 @@ public: DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl); ::decode(missing, bl); if (struct_v >= 4) { - map missing_flags; - ::decode(missing_flags, bl); - for (const auto &p : missing_flags) { - assert(missing.find(p.first) != missing.end()); - missing[p.first].flags = static_cast(p.second); - } + ::decode(may_include_deletes, bl); } DECODE_FINISH(bl); @@ -3939,6 +3949,7 @@ public: f->close_section(); } f->close_section(); + f->dump_bool("may_include_deletes", may_include_deletes); } template void filter_objects(F &&f) { @@ -3953,9 +3964,14 @@ public: static void generate_test_instances(list& o) { o.push_back(new pg_missing_set); o.push_back(new pg_missing_set); + o.back()->add( + hobject_t(object_t("foo"), "foo", 123, 456, 0, ""), + eversion_t(5, 6), eversion_t(5, 1), false); + o.push_back(new pg_missing_set); o.back()->add( hobject_t(object_t("foo"), "foo", 123, 456, 0, ""), eversion_t(5, 6), eversion_t(5, 1), true); + o.back()->may_include_deletes = true; } template void get_changed(F &&f) const { @@ -4024,7 +4040,8 @@ void decode(pg_missing_set &c, bufferlist::iterator &p) { template ostream& operator<<(ostream& out, const pg_missing_set &missing) { - out << "missing(" << missing.num_missing(); + out << "missing(" << missing.num_missing() + << " may_include_deletes = " << missing.may_include_deletes; //if (missing.num_lost()) out << ", " << missing.num_lost() << " lost"; out << ")"; return out; diff --git a/src/test/encoding/types.h b/src/test/encoding/types.h index 96fcd1747a8e..e762a2966e20 100644 --- a/src/test/encoding/types.h +++ b/src/test/encoding/types.h @@ -73,7 +73,7 @@ TYPE(pg_info_t) TYPE_FEATUREFUL(pg_query_t) TYPE(pg_log_entry_t) TYPE(pg_log_t) -TYPE(pg_missing_item) +TYPE_FEATUREFUL(pg_missing_item) TYPE(pg_missing_t) TYPE(pg_ls_response_t) TYPE(pg_nls_response_t) diff --git a/src/test/osd/TestPGLog.cc b/src/test/osd/TestPGLog.cc index b2fa2955cc6d..35b1ec49fc75 100644 --- a/src/test/osd/TestPGLog.cc +++ b/src/test/osd/TestPGLog.cc @@ -29,7 +29,9 @@ class PGLogTest : public ::testing::Test, protected PGLog { public: PGLogTest() : PGLog(g_ceph_context) {} - void SetUp() override { } + void SetUp() override { + missing.may_include_deletes = true; + } void TearDown() override { clear(); @@ -95,6 +97,7 @@ public: set toremove; list torollback; + bool deletes_during_peering; private: IndexedLog fullauth; @@ -102,7 +105,10 @@ public: pg_info_t authinfo; pg_info_t divinfo; public: + TestCase() : deletes_during_peering(false) {} void setup() { + init.may_include_deletes = !deletes_during_peering; + final.may_include_deletes = !deletes_during_peering; fullauth.log.insert(fullauth.log.end(), base.begin(), base.end()); fullauth.log.insert(fullauth.log.end(), auth.begin(), auth.end()); fulldiv.log.insert(fulldiv.log.end(), base.begin(), base.end()); @@ -248,7 +254,7 @@ public: pg_info_t oinfo = tcase.get_divinfo(); proc_replica_log( - oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0))); + oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0))); assert(oinfo.last_update >= log.tail); @@ -259,8 +265,13 @@ public: for (list::const_iterator i = tcase.auth.begin(); i != tcase.auth.end(); ++i) { - if (i->version > oinfo.last_update) - omissing.add_next_event(*i); + if (i->version > oinfo.last_update) { + if (i->is_delete() && tcase.deletes_during_peering) { + omissing.rm(i->soid, i->version); + } else { + omissing.add_next_event(*i); + } + } } verify_missing(tcase, omissing); } @@ -858,6 +869,7 @@ TEST_F(PGLogTest, merge_log) { oinfo.stats.reported_epoch = 1; log.tail = olog.tail = eversion_t(1, 1); log.head = olog.head = eversion_t(2, 1); + missing.may_include_deletes = false; EXPECT_FALSE(missing.have_missing()); EXPECT_EQ(0U, log.log.size()); @@ -933,6 +945,7 @@ TEST_F(PGLogTest, merge_log) { list remove_snap; bool dirty_info = false; bool dirty_big_info = false; + missing.may_include_deletes = false; { pg_log_entry_t e; @@ -1027,6 +1040,7 @@ TEST_F(PGLogTest, merge_log) { bool dirty_big_info = false; hobject_t divergent_object; + missing.may_include_deletes = true; { pg_log_entry_t e; @@ -1107,6 +1121,126 @@ TEST_F(PGLogTest, merge_log) { EXPECT_TRUE(dirty_big_info); } + /* +--------------------------+ + | log olog | + +--------+-------+---------+ + | |object | | + |version | hash | version | + | | | | + tail > (1,1) | x5 | (1,1) < tail + | | | | + | | | | + | (1,2) | x3 | (1,2) < lower_bound + | | | | + | | | | + head > (1,3) | x9 | | + | DELETE | | | + | | | | + | | x9 | (2,3) | + | | | MODIFY | + | | | | + | | x7 | (2,4) < head + | | | DELETE | + +--------+-------+---------+ + + The log entry (1,3) deletes the object x9 but the olog entry (2,3) modifies + it and is authoritative : the log entry (1,3) is divergent. + + */ + { + clear(); + + pg_log_t olog; + pg_info_t oinfo; + pg_shard_t fromosd; + pg_info_t info; + list remove_snap; + bool dirty_info = false; + bool dirty_big_info = false; + + hobject_t divergent_object; + + { + pg_log_entry_t e; + e.mark_unrollbackable(); + + e.version = eversion_t(1, 1); + e.soid.set_hash(0x5); + log.tail = e.version; + log.log.push_back(e); + e.version = eversion_t(1, 2); + e.soid.set_hash(0x3); + log.log.push_back(e); + e.version = eversion_t(1,3); + e.soid.set_hash(0x9); + divergent_object = e.soid; + e.op = pg_log_entry_t::DELETE; + log.log.push_back(e); + log.head = e.version; + log.index(); + + info.last_update = log.head; + + e.version = eversion_t(1, 1); + e.soid.set_hash(0x5); + olog.tail = e.version; + olog.log.push_back(e); + e.version = eversion_t(1, 2); + e.soid.set_hash(0x3); + olog.log.push_back(e); + e.version = eversion_t(2, 3); + e.soid.set_hash(0x9); + e.op = pg_log_entry_t::MODIFY; + olog.log.push_back(e); + e.version = eversion_t(2, 4); + e.soid.set_hash(0x7); + e.op = pg_log_entry_t::DELETE; + olog.log.push_back(e); + olog.head = e.version; + } + + snapid_t purged_snap(1); + { + oinfo.last_update = olog.head; + oinfo.purged_snaps.insert(purged_snap); + } + + EXPECT_FALSE(missing.have_missing()); + EXPECT_EQ(1U, log.objects.count(divergent_object)); + EXPECT_EQ(3U, log.log.size()); + EXPECT_TRUE(remove_snap.empty()); + EXPECT_EQ(log.head, info.last_update); + EXPECT_TRUE(info.purged_snaps.empty()); + EXPECT_FALSE(is_dirty()); + EXPECT_FALSE(dirty_info); + EXPECT_FALSE(dirty_big_info); + + TestHandler h(remove_snap); + missing.may_include_deletes = false; + merge_log(oinfo, olog, fromosd, info, &h, + dirty_info, dirty_big_info); + + /* When the divergent entry is a DELETE and the authoritative + entry is a MODIFY, the object will be added to missing : it is + a verifiable side effect proving the entry was identified + to be divergent. + */ + EXPECT_TRUE(missing.is_missing(divergent_object)); + EXPECT_EQ(1U, log.objects.count(divergent_object)); + EXPECT_EQ(4U, log.log.size()); + /* DELETE entries from olog that are appended to the hed of the + log, and the divergent version of the object is removed (added + to remove_snap). When peering handles deletes, it is the earlier + version that is in the removed list. + */ + EXPECT_EQ(0x7U, remove_snap.front().get_hash()); + EXPECT_EQ(log.head, info.last_update); + EXPECT_TRUE(info.purged_snaps.contains(purged_snap)); + EXPECT_TRUE(is_dirty()); + EXPECT_TRUE(dirty_info); + EXPECT_TRUE(dirty_big_info); + } + /* +--------------------------+ | log olog | +--------+-------+---------+ @@ -1184,6 +1318,7 @@ TEST_F(PGLogTest, merge_log) { EXPECT_FALSE(dirty_big_info); TestHandler h(remove_snap); + missing.may_include_deletes = false; merge_log(oinfo, olog, fromosd, info, &h, dirty_info, dirty_big_info); @@ -1239,6 +1374,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(last_update, oinfo.last_update); EXPECT_EQ(last_complete, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_FALSE(omissing.have_missing()); @@ -1312,6 +1448,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(olog.head, oinfo.last_update); EXPECT_EQ(olog.head, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_FALSE(omissing.have_missing()); @@ -1413,6 +1550,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(olog.head, oinfo.last_update); EXPECT_EQ(olog.head, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_TRUE(omissing.have_missing()); @@ -1499,6 +1637,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(olog.head, oinfo.last_update); EXPECT_EQ(olog.head, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_TRUE(omissing.have_missing()); @@ -1588,6 +1727,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(olog.head, oinfo.last_update); EXPECT_EQ(olog.head, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_TRUE(omissing.have_missing()); @@ -1681,6 +1821,7 @@ TEST_F(PGLogTest, proc_replica_log) { EXPECT_EQ(olog.head, oinfo.last_update); EXPECT_EQ(olog.head, oinfo.last_complete); + missing.may_include_deletes = false; proc_replica_log(oinfo, olog, omissing, from); EXPECT_TRUE(omissing.have_missing()); @@ -1803,6 +1944,20 @@ TEST_F(PGLogTest, merge_log_8) { run_test_case(t); } +TEST_F(PGLogTest, merge_log_9) { + TestCase t; + t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80))); + + t.auth.push_back(mk_ple_dt(mk_obj(1), mk_evt(11, 101), mk_evt(10, 100))); + + t.init.add(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80), false); + t.toremove.insert(mk_obj(1)); + t.deletes_during_peering = true; + + t.setup(); + run_test_case(t); +} + TEST_F(PGLogTest, merge_log_prior_version_have) { TestCase t; t.base.push_back(mk_ple_mod_rb(mk_obj(1), mk_evt(10, 100), mk_evt(8, 80))); diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index 64af93c962b2..c20f0287618e 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -480,8 +480,10 @@ int write_pg(ObjectStore::Transaction &t, epoch_t epoch, pg_info_t &info, t, &km, log, coll, info.pgid.make_pgmeta_oid(), divergent, true); } else { pg_missing_tracker_t tmissing(missing); + bool rebuilt_missing_set_with_deletes = false; PGLog::write_log_and_missing( - t, &km, log, coll, info.pgid.make_pgmeta_oid(), tmissing, true); + t, &km, log, coll, info.pgid.make_pgmeta_oid(), tmissing, true, + &rebuilt_missing_set_with_deletes); } t.omap_setkeys(coll, info.pgid.make_pgmeta_oid(), km); return 0;