From 9ad1f4f10ff7bfe32d0a37361640fe5c65e56699 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 6 Oct 2017 15:28:49 -0500 Subject: [PATCH] os/ObjectStore: 0-length zero does not change length of object Signed-off-by: Sage Weil --- src/os/ObjectStore.h | 7 +++ src/test/objectstore/store_test.cc | 77 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index c43090a2e28..65df8ec08eb 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -1051,6 +1051,8 @@ public: * newly provided data. More sophisticated implementations of * ObjectStore will omit the untouched data and store it as a * "hole" in the file. + * + * Note that a 0-length write does not affect the size of the object. */ void write(const coll_t& cid, const ghobject_t& oid, uint64_t off, uint64_t len, const bufferlist& write_data, uint32_t flags = 0) { @@ -1076,6 +1078,11 @@ public: * zero out the indicated byte range within an object. Some * ObjectStore instances may optimize this to release the * underlying storage space. + * + * If the zero range extends beyond the end of the object, the object + * size is extended, just as if we were writing a buffer full of zeros. + * EXCEPT if the length is 0, in which case (just like a 0-length write) + * we do not adjust the object size. */ void zero(const coll_t& cid, const ghobject_t& oid, uint64_t off, uint64_t len) { Op* _op = _get_next_op(); diff --git a/src/test/objectstore/store_test.cc b/src/test/objectstore/store_test.cc index 5defd3e3bb8..3fffab0e569 100644 --- a/src/test/objectstore/store_test.cc +++ b/src/test/objectstore/store_test.cc @@ -2260,6 +2260,55 @@ TEST_P(StoreTest, MiscFragmentTests) { } +TEST_P(StoreTest, ZeroVsObjectSize) { + ObjectStore::Sequencer osr("test"); + int r; + coll_t cid; + struct stat stat; + ghobject_t hoid(hobject_t(sobject_t("foo", 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 a; + a.append("stuff"); + { + ObjectStore::Transaction t; + t.write(cid, hoid, 0, 5, a); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(0, store->stat(cid, hoid, &stat)); + ASSERT_EQ(5, stat.st_size); + { + ObjectStore::Transaction t; + t.zero(cid, hoid, 1, 2); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(0, store->stat(cid, hoid, &stat)); + ASSERT_EQ(5, stat.st_size); + { + ObjectStore::Transaction t; + t.zero(cid, hoid, 3, 200); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(0, store->stat(cid, hoid, &stat)); + ASSERT_EQ(203, stat.st_size); + { + ObjectStore::Transaction t; + t.zero(cid, hoid, 100000, 200); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(r, 0); + } + ASSERT_EQ(0, store->stat(cid, hoid, &stat)); + ASSERT_EQ(100200, stat.st_size); +} + TEST_P(StoreTest, ZeroLengthWrite) { ObjectStore::Sequencer osr("test"); int r; @@ -2289,6 +2338,34 @@ TEST_P(StoreTest, ZeroLengthWrite) { ASSERT_EQ(0, r); } +TEST_P(StoreTest, ZeroLengthZero) { + ObjectStore::Sequencer osr("test"); + int r; + coll_t cid; + ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP))); + { + ObjectStore::Transaction t; + t.create_collection(cid, 0); + t.touch(cid, hoid); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(0, r); + } + { + ObjectStore::Transaction t; + t.zero(cid, hoid, 1048576, 0); + r = apply_transaction(store, &osr, std::move(t)); + ASSERT_EQ(0, r); + } + struct stat stat; + r = store->stat(cid, hoid, &stat); + ASSERT_EQ(0, r); + ASSERT_EQ(0, stat.st_size); + + bufferlist newdata; + r = store->read(cid, hoid, 0, 1048576, newdata); + ASSERT_EQ(0, r); +} + TEST_P(StoreTest, SimpleAttrTest) { ObjectStore::Sequencer osr("test"); int r; -- 2.39.5