]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: create+truncate for whole-object layered discards
authorIlya Dryomov <idryomov@gmail.com>
Thu, 8 Mar 2018 16:26:27 +0000 (17:26 +0100)
committerPrashant D <pdhange@redhat.com>
Tue, 13 Mar 2018 07:33:11 +0000 (03:33 -0400)
A whole-object layered discard is implemented as a truncate rather
than a delete: a dummy object is needed to prevent the CoW machinery
from kicking in.  However, a truncate on a non-existent object is
a no-op.  If the object doesn't exist in HEAD, a discard request is
effectively ignored -- parent blocks are still seen afterwards.

A non-exclusive create on an existing object is also a no-op, so the
fix is to do a compound create+truncate instead.

Fixes: http://tracker.ceph.com/issues/23285
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit 0514480b16b0a1e76a9ba31cc3ba58a32b7bee18)

src/librbd/io/ObjectRequest.h
src/test/librbd/io/test_mock_ObjectRequest.cc

index a015fb199ec9508580ce5f995037b008a82b20f0..f59ec2e2a1a7d4c2a571addbb01efcc8d84be9de 100644 (file)
@@ -366,7 +366,7 @@ public:
     case DISCARD_ACTION_REMOVE:
       return "remove";
     case DISCARD_ACTION_REMOVE_TRUNCATE:
-      return "remove (truncate)";
+      return "remove (create+truncate)";
     case DISCARD_ACTION_TRUNCATE:
       return "truncate";
     case DISCARD_ACTION_ZERO:
@@ -404,6 +404,8 @@ protected:
       wr->remove();
       break;
     case DISCARD_ACTION_REMOVE_TRUNCATE:
+      wr->create(false);
+      // fall through
     case DISCARD_ACTION_TRUNCATE:
       wr->truncate(this->m_object_off);
       break;
index 5a39689353511600588b8fa586a582a137a3018b..5f21416909afeec33ce2b95baf7f9fd262d15953 100644 (file)
@@ -289,6 +289,11 @@ struct TestMockIoObjectRequest : public TestMockFixture {
     }
   }
 
+  void expect_create(MockTestImageCtx &mock_image_ctx, bool exclusive) {
+    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), create(_, exclusive))
+      .Times(1);
+  }
+
   void expect_truncate(MockTestImageCtx &mock_image_ctx, int offset, int r) {
     auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx),
                                truncate(_, offset, _));
@@ -982,6 +987,7 @@ TEST_F(TestMockIoObjectRequest, DiscardRemoveTruncate) {
   expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096);
   expect_object_may_exist(mock_image_ctx, 0, false);
   expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0);
+  expect_create(mock_image_ctx, false);
   expect_truncate(mock_image_ctx, 0, 0);
 
   C_SaferCond ctx;