From e86ad68753407b841f54644d120242dcea1cd0e4 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 23 Sep 2016 16:40:36 -0400 Subject: [PATCH 1/2] os/bluestore: prevent extent merging across shard boundaries We cannot have a single extent span a shard boundary. If we reach a shard boundary, stop merging extents. Note that it might be better to move the shard boundary, but it is awkward to force that to happen at this point. Signed-off-by: Sage Weil --- src/os/bluestore/BlueStore.cc | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 069f8a0ce100f..2d25969cc203b 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -1888,6 +1888,20 @@ int BlueStore::ExtentMap::compress_extent_map(uint64_t offset, uint64_t length) if (p != extent_map.begin()) { --p; // start to the left of offset } + + // identify the *next* shard + auto pshard = shards.begin(); + while (pshard != shards.end() && + p->logical_offset >= pshard->offset) { + ++pshard; + } + uint64_t shard_end; + if (pshard != shards.end()) { + shard_end = pshard->offset; + } else { + shard_end = OBJECT_MAX_SIZE; + } + auto n = p; for (++n; n != extent_map.end(); p = n++) { if (n->logical_offset > offset + length) { @@ -1896,7 +1910,11 @@ int BlueStore::ExtentMap::compress_extent_map(uint64_t offset, uint64_t length) while (n != extent_map.end() && p->logical_offset + p->length == n->logical_offset && p->blob == n->blob && - p->blob_offset + p->length == n->blob_offset) { + p->blob_offset + p->length == n->blob_offset && + n->logical_offset < shard_end) { + dout(20) << __func__ << " 0x" << std::hex << offset << "~" << length + << " next shard 0x" << shard_end << std::dec + << " merging " << *p << " and " << *n << dendl; p->length += n->length; rm(n++); ++removed; @@ -1904,6 +1922,14 @@ int BlueStore::ExtentMap::compress_extent_map(uint64_t offset, uint64_t length) if (n == extent_map.end()) { break; } + if (n->logical_offset >= shard_end) { + ++pshard; + if (pshard != shards.end()) { + shard_end = pshard->offset; + } else { + shard_end = OBJECT_MAX_SIZE; + } + } } return removed; } From 4ece5b70d2de4a771b090eb20682e532fb59c09d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 23 Sep 2016 16:59:35 -0400 Subject: [PATCH 2/2] ceph_test_objectstore: add a test Signed-off-by: Sage Weil --- src/test/objectstore/store_test.cc | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/test/objectstore/store_test.cc b/src/test/objectstore/store_test.cc index 54ece21aefb37..d906ecb1c043b 100644 --- a/src/test/objectstore/store_test.cc +++ b/src/test/objectstore/store_test.cc @@ -3951,6 +3951,55 @@ TEST_P(StoreTest, SyntheticMatrixSharding) { do_matrix(m, store); } +TEST_P(StoreTest, ZipperPatternSharded) { + if(string(GetParam()) != "bluestore") + return; + g_conf->set_val("bluestore_min_alloc_size", "4096"); + g_ceph_context->_conf->apply_changes(NULL); + int r = store->umount(); + ASSERT_EQ(r, 0); + r = store->mount(); //to force min_alloc_size update + ASSERT_EQ(r, 0); + + ObjectStore::Sequencer osr("test"); + coll_t cid; + ghobject_t a(hobject_t(sobject_t("Object 1", CEPH_NOSNAP))); + { + ObjectStore::Transaction t; + t.create_collection(cid, 0); + cerr << "Creating collection " << cid << std::endl; + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + bufferlist bl; + int len = 4096; + bufferptr bp(len); + bp.zero(); + bl.append(bp); + for (int i=0; i<1000; ++i) { + ObjectStore::Transaction t; + t.write(cid, a, i*2*len, len, bl, 0); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + for (int i=0; i<1000; ++i) { + ObjectStore::Transaction t; + t.write(cid, a, i*2*len + 1, len, bl, 0); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + { + ObjectStore::Transaction t; + t.remove(cid, a); + t.remove_collection(cid); + cerr << "Cleaning" << std::endl; + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + g_conf->set_val("bluestore_min_alloc_size", "0"); + g_ceph_context->_conf->apply_changes(NULL); +} + TEST_P(StoreTest, SyntheticMatrixCsumAlgorithm) { if (string(GetParam()) != "bluestore") return;