ObjectStore::Transaction t;
t.remove(cid, hoid);
t.remove(cid, hoid2);
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+}
+
+#if defined(WITH_BLUESTORE)
+TEST_P(StoreTest, BlueStoreUnshareBlobTest) {
+ if (string(GetParam()) != "bluestore")
+ return;
+ int r;
+ coll_t cid;
+ auto ch = store->create_new_collection(cid);
+ {
+ ObjectStore::Transaction t;
+ t.create_collection(cid, 0);
+ cerr << "Creating collection " << cid << std::endl;
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+ ghobject_t hoid(hobject_t(sobject_t("Object 1", CEPH_NOSNAP)));
+ hoid.hobj.pool = -1;
+ ghobject_t hoid2(hobject_t(sobject_t("Object 1", CEPH_NOSNAP)));
+ hoid2.hobj.pool = -1;
+ hoid2.generation = 2;
+ {
+ // check if blob is unshared properly
+ bufferlist data, newdata;
+ data.append(string(8192, 'a'));
+
+ ObjectStore::Transaction t;
+ t.write(cid, hoid, 0, data.length(), data);
+ cerr << "Creating object and write 8K " << hoid << std::endl;
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+
+ ObjectStore::Transaction t2;
+ t2.clone_range(cid, hoid, hoid2, 0, 4096, 0);
+ cerr << "Clone range object" << std::endl;
+ r = queue_transaction(store, ch, std::move(t2));
+ ASSERT_EQ(r, 0);
+
+ data.clear();
+ data.append(string(4096, 'b'));
+
+ ObjectStore::Transaction t3;
+ t3.write(cid, hoid, 0, data.length(), data);
+ cerr << "Writing 4k to source object " << hoid << std::endl;
+ r = queue_transaction(store, ch, std::move(t3));
+ ASSERT_EQ(r, 0);
+
+ {
+ // this trims hoid one out of onode cache
+ EXPECT_EQ(store->umount(), 0);
+ EXPECT_EQ(store->mount(), 0);
+ ch = store->open_collection(cid);
+ }
+
+ ObjectStore::Transaction t4;
+ t4.remove(cid, hoid2);
+ cerr << "Deleting dest object" << hoid2 << std::endl;
+ r = queue_transaction(store, ch, std::move(t4));
+ ASSERT_EQ(r, 0);
+
+ bufferlist resdata;
+ r = store->read(ch, hoid, 0, 0x2000, resdata);
+ ASSERT_EQ(r, 0x2000);
+
+ {
+ BlueStore* bstore = dynamic_cast<BlueStore*> (store.get());
+ auto* kv = bstore->get_kv();
+
+ // to be inline with BlueStore.cc
+ const string PREFIX_SHARED_BLOB = "X";
+
+ size_t cnt = 0;
+ auto it = kv->get_iterator(PREFIX_SHARED_BLOB);
+ ceph_assert(it);
+ for (it->lower_bound(string()); it->valid(); it->next()) {
+ ++cnt;
+ }
+ ASSERT_EQ(cnt, 0);
+ }
+ }
+ {
+ ObjectStore::Transaction t;
+ t.remove(cid, hoid);
t.remove_collection(cid);
cerr << "Cleaning" << std::endl;
r = queue_transaction(store, ch, std::move(t));
}
}
+TEST_P(StoreTest, BlueStoreUnshareBlobBugTest) {
+ if (string(GetParam()) != "bluestore")
+ return;
+ int r;
+ coll_t cid;
+ auto ch = store->create_new_collection(cid);
+ {
+ ObjectStore::Transaction t;
+ t.create_collection(cid, 0);
+ cerr << "Creating collection " << cid << std::endl;
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+ ghobject_t hoid(hobject_t(sobject_t("Object 1", CEPH_NOSNAP)));
+ hoid.hobj.pool = -1;
+ ghobject_t hoid2(hobject_t(sobject_t("Object 1", CEPH_NOSNAP)));
+ hoid2.hobj.pool = -1;
+ hoid2.generation = 2;
+ {
+ // check if blob is unshared properly
+ bufferlist data, newdata;
+ data.append(string(8192, 'a'));
+
+ ObjectStore::Transaction t;
+ t.write(cid, hoid, 0, data.length(), data);
+ cerr << "Creating object and write 8K " << hoid << std::endl;
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+
+ ObjectStore::Transaction t2;
+ t2.clone_range(cid, hoid, hoid2, 0, 4096, 0);
+ cerr << "Clone range object" << std::endl;
+ r = queue_transaction(store, ch, std::move(t2));
+ ASSERT_EQ(r, 0);
+
+ data.clear();
+ data.append(string(4096, 'b'));
+
+ ObjectStore::Transaction t3;
+ t3.write(cid, hoid, 0, data.length(), data);
+ cerr << "Writing 4k to source object " << hoid << std::endl;
+ r = queue_transaction(store, ch, std::move(t3));
+ ASSERT_EQ(r, 0);
+
+ {
+ // this trims hoid one out of onode cache
+ EXPECT_EQ(store->umount(), 0);
+ EXPECT_EQ(store->mount(), 0);
+ ch = store->open_collection(cid);
+ }
+
+ ObjectStore::Transaction t4;
+ t4.write(cid, hoid2, 0, data.length(), data);
+ cerr << "Writing 4k to second object " << hoid2 << std::endl;
+ r = queue_transaction(store, ch, std::move(t4));
+ ASSERT_EQ(r, 0);
+
+ bufferlist resdata;
+ r = store->read(ch, hoid, 0, 0x2000, resdata);
+ ASSERT_EQ(r, 0x2000);
+
+ {
+ BlueStore* bstore = dynamic_cast<BlueStore*> (store.get());
+ auto* kv = bstore->get_kv();
+
+ // to be inline with BlueStore.cc
+ const string PREFIX_SHARED_BLOB = "X";
+
+ size_t cnt = 0;
+ auto it = kv->get_iterator(PREFIX_SHARED_BLOB);
+ ceph_assert(it);
+ for (it->lower_bound(string()); it->valid(); it->next()) {
+ ++cnt;
+ }
+ // This shows a bug in unsharing a blob,
+ // after writing to 0x0~1000 to hoid2 share blob at hoid should be
+ //unshared but it doesn't in the current implementation
+ ASSERT_EQ(cnt, 1);
+ }
+ }
+ {
+ ObjectStore::Transaction t;
+ t.remove(cid, hoid);
+ t.remove(cid, hoid2);
+ t.remove_collection(cid);
+ cerr << "Cleaning" << std::endl;
+ r = queue_transaction(store, ch, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+}
+#endif
TEST_P(StoreTest, SimpleObjectLongnameTest) {
int r;