librbd/deep_copy: adjust in-memory overlap if set_size updated it on disk
authorMykola Golub <mgolub@suse.com>
Thu, 10 May 2018 18:25:17 +0000 (21:25 +0300)
committerJason Dillaman <dillaman@redhat.com>
Wed, 16 May 2018 18:06:17 +0000 (14:06 -0400)
so set_parent won't be called when overlap is changed due to image
size change.

Signed-off-by: Mykola Golub <mgolub@suse.com>
(cherry picked from commit ca0893c4d9f54e3d80cf7ea90c8b4431d1f5a4f0)

src/librbd/deep_copy/SetHeadRequest.cc
src/test/librbd/deep_copy/test_mock_SetHeadRequest.cc

index 067c2979a57d74de3041ac120b00694392e99549..cab319820c15f9c73669b128e9f4c5e2d11d8768 100644 (file)
@@ -27,6 +27,7 @@ SetHeadRequest<I>::SetHeadRequest(I *image_ctx, uint64_t size,
   : m_image_ctx(image_ctx), m_size(size), m_parent_spec(spec),
     m_parent_overlap(parent_overlap), m_on_finish(on_finish),
     m_cct(image_ctx->cct) {
+  assert(m_parent_overlap <= m_size);
 }
 
 template <typename I>
@@ -84,6 +85,13 @@ void SetHeadRequest<I>::handle_set_size(int r) {
   {
     // adjust in-memory image size now that it's updated on disk
     RWLock::WLocker snap_locker(m_image_ctx->snap_lock);
+    if (m_image_ctx->size > m_size) {
+      RWLock::WLocker parent_locker(m_image_ctx->parent_lock);
+      if (m_image_ctx->parent_md.spec.pool_id != -1 &&
+          m_image_ctx->parent_md.overlap > m_size) {
+        m_image_ctx->parent_md.overlap = m_size;
+      }
+    }
     m_image_ctx->size = m_size;
   }
 
index b29b875e27d9c566484a0ac8a87bae793daaa20c..9d2d51cdb702b2ad8a604845aa3fb361e225eb74 100644 (file)
@@ -201,16 +201,18 @@ TEST_F(TestMockDeepCopySetHeadRequest, SetParentOverlap) {
   mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
 
   mock_image_ctx.parent_md.spec = {123, "test", 0};
+  mock_image_ctx.parent_md.overlap = m_image_ctx->size;
 
   InSequence seq;
   expect_start_op(mock_exclusive_lock);
-  expect_set_parent(mock_image_ctx, 0);
+  expect_set_size(mock_image_ctx, 0);
 
   C_SaferCond ctx;
-  auto request = create_request(mock_image_ctx, m_image_ctx->size,
+  auto request = create_request(mock_image_ctx, 123,
                                 mock_image_ctx.parent_md.spec, 123, &ctx);
   request->send();
   ASSERT_EQ(0, ctx.wait());
+  ASSERT_EQ(123, mock_image_ctx.parent_md.overlap);
 }
 
 TEST_F(TestMockDeepCopySetHeadRequest, SetParentError) {