}
+TEST_P(StoreTest, BluestoreRepairGlobalStats)
+{
+ if (string(GetParam()) != "bluestore")
+ return;
+ const size_t offs_base = 65536 / 2;
+
+ BlueStore* bstore = dynamic_cast<BlueStore*> (store.get());
+
+ // start with global stats
+ bstore->inject_global_statfs({});
+ bstore->umount();
+ SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "false");
+ bstore->mount();
+
+ // fill the store with some data
+ const uint64_t pool = 555;
+ coll_t cid(spg_t(pg_t(0, pool), shard_id_t::NO_SHARD));
+ auto ch = store->create_new_collection(cid);
+
+ ghobject_t hoid = make_object("Object 1", pool);
+ ghobject_t hoid_dup = make_object("Object 1(dup)", pool);
+ ghobject_t hoid2 = make_object("Object 2", pool);
+ ghobject_t hoid_cloned = hoid2;
+ hoid_cloned.hobj.snap = 1;
+ ghobject_t hoid3 = make_object("Object 3", pool);
+ ghobject_t hoid3_cloned = hoid3;
+ hoid3_cloned.hobj.snap = 1;
+ bufferlist bl;
+ bl.append("1234512345");
+ int r;
+ const size_t repeats = 16;
+ {
+ auto ch = store->create_new_collection(cid);
+ cerr << "create collection + write" << std::endl;
+ ObjectStore::Transaction t;
+ t.create_collection(cid, 0);
+ for( auto i = 0ul; i < repeats; ++i ) {
+ t.write(cid, hoid, i * offs_base, bl.length(), bl);
+ t.write(cid, hoid_dup, i * offs_base, bl.length(), bl);
+ }
+ for( auto i = 0ul; i < repeats; ++i ) {
+ t.write(cid, hoid2, i * offs_base, bl.length(), bl);
+ }
+ t.clone(cid, hoid2, hoid_cloned);
+
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+
+ bstore->umount();
+
+ // enable per-pool stats collection hence causing fsck to fail
+ cerr << "per-pool statfs" << std::endl;
+ SetVal(g_conf(), "bluestore_fsck_error_on_no_per_pool_stats", "true");
+ g_ceph_context->_conf.apply_changes(nullptr);
+
+ ASSERT_EQ(bstore->fsck(false), 1);
+ ASSERT_EQ(bstore->repair(false), 0);
+ ASSERT_EQ(bstore->fsck(false), 0);
+
+ bstore->mount();
+}
+
+TEST_P(StoreTest, BluestoreRepairGlobalStatsFixOnMount)
+{
+ if (string(GetParam()) != "bluestore")
+ return;
+ const size_t offs_base = 65536 / 2;
+
+ BlueStore* bstore = dynamic_cast<BlueStore*> (store.get());
+
+ // start with global stats
+ bstore->inject_global_statfs({});
+ bstore->umount();
+ SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "false");
+ bstore->mount();
+
+ // fill the store with some data
+ const uint64_t pool = 555;
+ coll_t cid(spg_t(pg_t(0, pool), shard_id_t::NO_SHARD));
+ auto ch = store->create_new_collection(cid);
+
+ ghobject_t hoid = make_object("Object 1", pool);
+ ghobject_t hoid_dup = make_object("Object 1(dup)", pool);
+ ghobject_t hoid2 = make_object("Object 2", pool);
+ ghobject_t hoid_cloned = hoid2;
+ hoid_cloned.hobj.snap = 1;
+ ghobject_t hoid3 = make_object("Object 3", pool);
+ ghobject_t hoid3_cloned = hoid3;
+ hoid3_cloned.hobj.snap = 1;
+ bufferlist bl;
+ bl.append("1234512345");
+ int r;
+ const size_t repeats = 16;
+ {
+ auto ch = store->create_new_collection(cid);
+ cerr << "create collection + write" << std::endl;
+ ObjectStore::Transaction t;
+ t.create_collection(cid, 0);
+ for( auto i = 0ul; i < repeats; ++i ) {
+ t.write(cid, hoid, i * offs_base, bl.length(), bl);
+ t.write(cid, hoid_dup, i * offs_base, bl.length(), bl);
+ }
+ for( auto i = 0ul; i < repeats; ++i ) {
+ t.write(cid, hoid2, i * offs_base, bl.length(), bl);
+ }
+ t.clone(cid, hoid2, hoid_cloned);
+
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+
+ bstore->umount();
+
+ // enable per-pool stats collection hence causing fsck to fail
+ cerr << "per-pool statfs" << std::endl;
+ SetVal(g_conf(), "bluestore_fsck_error_on_no_per_pool_stats", "true");
+ g_ceph_context->_conf.apply_changes(nullptr);
+
+ ASSERT_EQ(bstore->fsck(false), 1);
+
+ SetVal(g_conf(), "bluestore_fsck_quick_fix_on_mount", "true");
+ bstore->mount();
+ bstore->umount();
+ ASSERT_EQ(bstore->fsck(false), 0);
+
+ bstore->mount();
+}
+
TEST_P(StoreTest, BluestoreStatistics) {
if (string(GetParam()) != "bluestore")
return;