From: Igor Fedotov Date: Mon, 3 Feb 2020 15:36:21 +0000 (+0300) Subject: os/bluestore: fix unused 'tail' calculation. X-Git-Tag: v16.1.0~2752^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c91cc3a8d689995e8554c41c9b0f652d9a3458da;p=ceph.git os/bluestore: fix unused 'tail' calculation. Fixes: https://tracker.ceph.com/issues/41901 Signed-off-by: Igor Fedotov --- diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index e1a41ce0b221..efa7091591b7 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -13520,12 +13520,14 @@ int BlueStore::_do_alloc_write( } if (wi.mark_unused) { + ceph_assert(!dblob.is_compressed()); auto b_end = b_off + wi.bl.length(); if (b_off) { dblob.add_unused(0, b_off); } - if (b_end < wi.blob_length) { - dblob.add_unused(b_end, wi.blob_length - b_end); + uint64_t llen = dblob.get_logical_length(); + if (b_end < llen) { + dblob.add_unused(b_end, llen - b_end); } } diff --git a/src/os/bluestore/bluestore_types.h b/src/os/bluestore/bluestore_types.h index 63f7c0fd8abf..7ed4eb7b04de 100644 --- a/src/os/bluestore/bluestore_types.h +++ b/src/os/bluestore/bluestore_types.h @@ -633,6 +633,7 @@ public: if (!has_unused()) { return false; } + ceph_assert(!is_compressed()); uint64_t blob_len = get_logical_length(); ceph_assert((blob_len % (sizeof(unused)*8)) == 0); ceph_assert(offset + length <= blob_len); @@ -648,6 +649,7 @@ public: /// mark a range that has never been used void add_unused(uint64_t offset, uint64_t length) { + ceph_assert(!is_compressed()); uint64_t blob_len = get_logical_length(); ceph_assert((blob_len % (sizeof(unused)*8)) == 0); ceph_assert(offset + length <= blob_len); @@ -665,6 +667,7 @@ public: /// indicate that a range has (now) been used. void mark_used(uint64_t offset, uint64_t length) { if (has_unused()) { + ceph_assert(!is_compressed()); uint64_t blob_len = get_logical_length(); ceph_assert((blob_len % (sizeof(unused)*8)) == 0); ceph_assert(offset + length <= blob_len); diff --git a/src/test/objectstore/store_test.cc b/src/test/objectstore/store_test.cc index 8cc2d92fee6a..ecfd30508c5f 100644 --- a/src/test/objectstore/store_test.cc +++ b/src/test/objectstore/store_test.cc @@ -1315,6 +1315,99 @@ TEST_P(StoreTest, SimpleObjectTest) { #if defined(WITH_BLUESTORE) +TEST_P(StoreTestSpecificAUSize, ReproBug41901Test) { + if(string(GetParam()) != "bluestore") + return; + SetVal(g_conf(), "bluestore_debug_enforce_settings", "hdd"); + g_conf().apply_changes(nullptr); + StartDeferred(65536); + + int r; + coll_t cid; + ghobject_t hoid(hobject_t(sobject_t("Object 1", CEPH_NOSNAP))); + const PerfCounters* logger = store->get_perf_counters(); + 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); + } + { + bool exists = store->exists(ch, hoid); + ASSERT_TRUE(!exists); + + ObjectStore::Transaction t; + t.touch(cid, hoid); + cerr << "Creating object " << hoid << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + + exists = store->exists(ch, hoid); + ASSERT_EQ(true, exists); + } + { + ObjectStore::Transaction t; + bufferlist bl, orig; + string s(4096, 'a'); + bl.append(s); + t.write(cid, hoid, 0x11000, bl.length(), bl); + cerr << "write1" << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + { + ObjectStore::Transaction t; + bufferlist bl, orig; + string s(4096 * 3, 'a'); + bl.append(s); + t.write(cid, hoid, 0x15000, bl.length(), bl); + cerr << "write2" << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(logger->get(l_bluestore_write_small), 2u); + ASSERT_EQ(logger->get(l_bluestore_write_small_unused), 1u); + + { + ObjectStore::Transaction t; + bufferlist bl, orig; + string s(4096 * 2, 'a'); + bl.append(s); + t.write(cid, hoid, 0xe000, bl.length(), bl); + cerr << "write3" << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(logger->get(l_bluestore_write_small), 3u); + ASSERT_EQ(logger->get(l_bluestore_write_small_unused), 2u); + + + { + ObjectStore::Transaction t; + bufferlist bl, orig; + string s(4096, 'a'); + bl.append(s); + t.write(cid, hoid, 0xf000, bl.length(), bl); + t.write(cid, hoid, 0x10000, bl.length(), bl); + cerr << "write3" << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(logger->get(l_bluestore_write_small), 5u); + ASSERT_EQ(logger->get(l_bluestore_write_small_unused), 2u); + { + ObjectStore::Transaction t; + t.remove(cid, hoid); + t.remove_collection(cid); + cerr << "Cleaning" << std::endl; + r = queue_transaction(store, ch, std::move(t)); + ASSERT_EQ(r, 0); + } +} + + TEST_P(StoreTestSpecificAUSize, BluestoreStatFSTest) { if(string(GetParam()) != "bluestore") return;