From 263e84427dc31b745b559a8b08b6fbf8764d46ad Mon Sep 17 00:00:00 2001 From: Igor Fedotov Date: Mon, 27 Jan 2020 21:11:51 +0300 Subject: [PATCH] test/store_test: introduce test case for per-pool omap repair. This also reproduces https://tracker.ceph.com/issues/43824 Signed-off-by: Igor Fedotov --- src/os/bluestore/BlueStore.cc | 31 +++++++++++ src/os/bluestore/BlueStore.h | 4 ++ src/test/objectstore/store_test.cc | 87 ++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 900520d545ad5..deb3a824251bf 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -8906,6 +8906,37 @@ void BlueStore::inject_false_free(coll_t cid, ghobject_t oid) db->submit_transaction_sync(txn); } +void BlueStore::inject_legacy_omap() +{ + dout(1) << __func__ << dendl; + per_pool_omap = false; + KeyValueDB::Transaction txn; + txn = db->get_transaction(); + txn->rmkey(PREFIX_SUPER, "per_pool_omap"); + db->submit_transaction_sync(txn); +} + +void BlueStore::inject_legacy_omap(coll_t cid, ghobject_t oid) +{ + dout(1) << __func__ << " " + << cid << " " << oid + <lock }; // just to avoid internal asserts + o = c->get_onode(oid, false); + ceph_assert(o); + } + o->onode.clear_flag(bluestore_onode_t::FLAG_PERPOOL_OMAP | bluestore_onode_t::FLAG_PGMETA_OMAP); + txn = db->get_transaction(); + _record_onode(o, txn); + db->submit_transaction_sync(txn); +} + + void BlueStore::inject_statfs(const string& key, const store_statfs_t& new_statfs) { BlueStoreRepairer repairer; diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 63f1acaa2f50b..af514427c9273 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -2840,6 +2840,10 @@ public: void inject_misreference(coll_t cid1, ghobject_t oid1, coll_t cid2, ghobject_t oid2, uint64_t offset); + // resets global per_pool_omap in DB + void inject_legacy_omap(); + // resets per_pool_omap | pgmeta_omap for onode + void inject_legacy_omap(coll_t cid, ghobject_t oid); void compact() override { ceph_assert(db); diff --git a/src/test/objectstore/store_test.cc b/src/test/objectstore/store_test.cc index f296a61711d73..8cc2d92fee6aa 100644 --- a/src/test/objectstore/store_test.cc +++ b/src/test/objectstore/store_test.cc @@ -7640,6 +7640,93 @@ TEST_P(StoreTest, BluestoreStatistics) { cout << std::endl; } +TEST_P(StoreTest, BluestorePerPoolOmapFixOnMount) +{ + if (string(GetParam()) != "bluestore") + return; + + BlueStore* bstore = dynamic_cast (store.get()); + const uint64_t pool = 555; + coll_t cid(spg_t(pg_t(0, pool), shard_id_t::NO_SHARD)); + ghobject_t oid = make_object("Object 1", pool); + ghobject_t oid2 = make_object("Object 2", pool); + // fill the store with some data + auto ch = store->create_new_collection(cid); + map omap; + bufferlist h; + h.append("header"); + { + omap["omap_key"].append("omap value"); + ObjectStore::Transaction t; + t.create_collection(cid, 0); + t.touch(cid, oid); + t.omap_setheader(cid, oid, h); + t.touch(cid, oid2); + t.omap_setheader(cid, oid2, h); + int r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + + // inject legacy omaps + bstore->inject_legacy_omap(); + bstore->inject_legacy_omap(cid, oid); + bstore->inject_legacy_omap(cid, oid2); + + bstore->umount(); + + // check we injected an issue + SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "false"); + SetVal(g_conf(), "bluestore_fsck_error_on_no_per_pool_omap", "true"); + g_ceph_context->_conf.apply_changes(nullptr); + ASSERT_EQ(bstore->fsck(false), 3); + + // set autofix and mount + SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "true"); + g_ceph_context->_conf.apply_changes(nullptr); + bstore->mount(); + bstore->umount(); + + // check we fixed it.. + ASSERT_EQ(bstore->fsck(false), 0); + bstore->mount(); + + // + // Now repro https://tracker.ceph.com/issues/43824 + // + // inject legacy omaps again + bstore->inject_legacy_omap(); + bstore->inject_legacy_omap(cid, oid); + bstore->inject_legacy_omap(cid, oid2); + bstore->umount(); + + // check we injected an issue + SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "true"); + SetVal(g_conf(), "bluestore_fsck_error_on_no_per_pool_omap", "true"); + g_ceph_context->_conf.apply_changes(nullptr); + bstore->mount(); + ch = store->open_collection(cid); + + { + // write to onode which will partiall revert per-pool + // omap repair done on mount due to #43824. + // And object removal will leave stray per-pool omap recs + // + ObjectStore::Transaction t; + bufferlist bl; + bl.append("data"); + //this triggers onode rec update and hence legacy omap + t.write(cid, oid, 0, bl.length(), bl); + t.remove(cid, oid2); // this will trigger stray per-pool omap + int r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + bstore->umount(); + // check omap's been fixed. + ASSERT_EQ(bstore->fsck(false), 0); // this will fail without fix for #43824 + + bstore->mount(); +} + TEST_P(StoreTestSpecificAUSize, BluestoreTinyDevFailure) { if (string(GetParam()) != "bluestore") return; -- 2.39.5