]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: create+truncate for whole-object layered discards 20809/head
authorIlya Dryomov <idryomov@gmail.com>
Thu, 8 Mar 2018 16:26:27 +0000 (17:26 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 9 Mar 2018 09:18:04 +0000 (10:18 +0100)
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>
src/librbd/io/ObjectRequest.h
src/test/librbd/io/test_mock_ObjectRequest.cc

index f51263326937d5283e376170ddb1ebccd57e05b2..3ea10c04058c24fd472c5765e272736d6354502e 100644 (file)
@@ -357,7 +357,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:
@@ -395,6 +395,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 1953b067a2f782e35b79121bf1424945a75f25ab..449f8058c321d9462edc4dfcf0797e190c73a398 100644 (file)
@@ -288,6 +288,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, _));
@@ -1000,6 +1005,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;