]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: disable image mirroring when moving to trash
authorMykola Golub <mgolub@suse.com>
Wed, 12 Dec 2018 15:42:49 +0000 (15:42 +0000)
committerMykola Golub <mgolub@suse.com>
Thu, 16 May 2019 12:47:28 +0000 (13:47 +0100)
And enable when restoring if mirror pool mode set.

Fixes: https://tracker.ceph.com/issues/37596
Signed-off-by: Mykola Golub <mgolub@suse.com>
(cherry picked from commit 6844a52ebbc45a046b4a94909b48bc4fc0c305c7)

Conflicts:
src/librbd/api/Trash.cc (the code is in src/librbd/internal.cc)

src/librbd/internal.cc
src/test/librbd/test_mirroring.cc

index 2e08b5e92310685d6ed80cfa0ac9ab4016d5c75f..ed9f9ac330b8588ab19a9c189665da6cad6450ab 100644 (file)
@@ -48,6 +48,7 @@
 #include "librbd/io/ReadResult.h"
 #include "librbd/journal/Types.h"
 #include "librbd/managed_lock/Types.h"
+#include "librbd/mirror/DisableRequest.h"
 #include "librbd/mirror/EnableRequest.h"
 #include "librbd/operation/TrimRequest.h"
 #include "librbd/trash/MoveRequest.h"
@@ -125,6 +126,86 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2)
     return false;
 }
 
+int disable_mirroring(ImageCtx *ictx) {
+  if (!ictx->test_features(RBD_FEATURE_JOURNALING)) {
+    return 0;
+  }
+
+  cls::rbd::MirrorImage mirror_image;
+  int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, &mirror_image);
+  if (r == -ENOENT) {
+    ldout(ictx->cct, 10) << "mirroring is not enabled for this image" << dendl;
+    return 0;
+  }
+
+  if (r < 0) {
+    lderr(ictx->cct) << "failed to retrieve mirror image: " << cpp_strerror(r)
+                     << dendl;
+    return r;
+  }
+
+  ldout(ictx->cct, 10) << dendl;
+
+  C_SaferCond ctx;
+  auto req = mirror::DisableRequest<>::create(ictx, false, true, &ctx);
+  req->send();
+  r = ctx.wait();
+  if (r < 0) {
+    lderr(ictx->cct) << "failed to disable mirroring: " << cpp_strerror(r)
+                     << dendl;
+    return r;
+  }
+
+  return 0;
+}
+
+int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) {
+  auto cct = reinterpret_cast<CephContext*>(io_ctx.cct());
+
+  uint64_t features;
+  int r = cls_client::get_features(&io_ctx, util::header_name(image_id),
+                                   CEPH_NOSNAP, &features);
+  if (r < 0) {
+    lderr(cct) << "failed to retrieve features: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  if ((features & RBD_FEATURE_JOURNALING) == 0) {
+    return 0;
+  }
+
+  cls::rbd::MirrorMode mirror_mode;
+  r = cls_client::mirror_mode_get(&io_ctx, &mirror_mode);
+  if (r < 0 && r != -ENOENT) {
+    lderr(cct) << "failed to retrieve mirror mode: " << cpp_strerror(r)
+               << dendl;
+    return r;
+  }
+
+  if (mirror_mode != cls::rbd::MIRROR_MODE_POOL) {
+    ldout(cct, 10) << "not pool mirroring mode" << dendl;
+    return 0;
+  }
+
+  ldout(cct, 10) << dendl;
+
+  ThreadPool *thread_pool;
+  ContextWQ *op_work_queue;
+  ImageCtx::get_thread_pool_instance(cct, &thread_pool, &op_work_queue);
+  C_SaferCond ctx;
+  auto req = mirror::EnableRequest<>::create(io_ctx, image_id, "",
+                                             op_work_queue, &ctx);
+  req->send();
+  r = ctx.wait();
+  if (r < 0) {
+    lderr(cct) << "failed to enable mirroring: " << cpp_strerror(r)
+               << dendl;
+    return r;
+  }
+
+  return 0;
+}
+
 } // anonymous namespace
 
   int detect_format(IoCtx &io_ctx, const string &name,
@@ -1409,6 +1490,12 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2)
     }
     ictx->owner_lock.put_read();
 
+    r = disable_mirroring(ictx);
+    if (r < 0) {
+      ictx->state->close();
+      return r;
+    }
+
     utime_t delete_time{ceph_clock_now()};
     utime_t deferment_end_time{delete_time};
     deferment_end_time += delay;
@@ -1603,6 +1690,11 @@ bool compare_by_name(const child_info_t& c1, const child_info_t& c2)
       return r;
     }
 
+    r = enable_mirroring(io_ctx, image_id);
+    if (r < 0) {
+      // not fatal -- ignore
+    }
+
     ldout(cct, 2) << "removing image from trash..." << dendl;
     r = cls_client::trash_remove(&io_ctx, image_id);
     if (r < 0 && r != -ENOENT) {
index ce21e3f87567c45142bd07707456ce5c0bb7e191..bade0e7f74e4636e8aa1fb69de5ba2f53214e462 100644 (file)
@@ -263,6 +263,45 @@ public:
     ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED));
   }
 
+  void check_trash_move_restore(rbd_mirror_mode_t mirror_mode,
+                                bool enable_mirroring) {
+
+    ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode));
+
+    int order = 20;
+    uint64_t features = RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING;
+    ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
+                               &order));
+    librbd::Image image;
+    ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
+
+    if (enable_mirroring) {
+      ASSERT_EQ(0, image.mirror_image_enable());
+    }
+
+    std::string image_id;
+    ASSERT_EQ(0, image.get_id(&image_id));
+
+    ASSERT_EQ(0, m_rbd.trash_move(m_ioctx, image_name.c_str(), 100));
+
+    librbd::mirror_image_info_t mirror_image;
+    ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
+    ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_DISABLED);
+
+    ASSERT_EQ(0, m_rbd.trash_restore(m_ioctx, image_id.c_str(), ""));
+
+    ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
+    if (mirror_mode == RBD_MIRROR_MODE_POOL) {
+      ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_ENABLED);
+    } else {
+      ASSERT_EQ(mirror_image.state, RBD_MIRROR_IMAGE_DISABLED);
+    }
+
+    image.close();
+    ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
+    ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED));
+  }
+
   void setup_mirror_peer(librados::IoCtx &io_ctx, librbd::Image &image) {
     ASSERT_EQ(0, image.snap_create("sync-point-snap"));
 
@@ -619,6 +658,18 @@ TEST_F(TestMirroring, RemoveImage_With_MirrorImageDemoted) {
                      true, true);
 }
 
+TEST_F(TestMirroring, TrashMoveRestore_PoolMode) {
+  check_trash_move_restore(RBD_MIRROR_MODE_POOL, false);
+}
+
+TEST_F(TestMirroring, TrashMoveRestore_ImageMode_MirroringDisabled) {
+  check_trash_move_restore(RBD_MIRROR_MODE_IMAGE, false);
+}
+
+TEST_F(TestMirroring, TrashMoveRestore_ImageMode_MirroringEnabled) {
+  check_trash_move_restore(RBD_MIRROR_MODE_IMAGE, true);
+}
+
 TEST_F(TestMirroring, MirrorStatusList) {
   std::vector<uint64_t>
       features_vec(5, RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING);