]> git.apps.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>
Fri, 14 Dec 2018 16:47:15 +0000 (16:47 +0000)
And enable when restoring if mirror pool mode set.

Fixes: https://tracker.ceph.com/issues/37596
Signed-off-by: Mykola Golub <mgolub@suse.com>
src/librbd/api/Trash.cc
src/test/librbd/test_mirroring.cc

index c8c40a1eefebf61473f4d7fff8055e00f4ed11c4..319be136b58931f84b99f21d7baaa3f078801e13 100644 (file)
@@ -15,6 +15,8 @@
 #include "librbd/TrashWatcher.h"
 #include "librbd/Utils.h"
 #include "librbd/api/Image.h"
+#include "librbd/mirror/DisableRequest.h"
+#include "librbd/mirror/EnableRequest.h"
 #include "librbd/trash/MoveRequest.h"
 
 #define dout_subsys ceph_subsys_rbd
 namespace librbd {
 namespace api {
 
+namespace {
+
+template <typename I>
+int disable_mirroring(I *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<I>::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;
+}
+
+template <typename I>
+int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) {
+  auto cct = reinterpret_cast<CephContext*>(io_ctx.cct());
+
+  uint64_t features;
+  uint64_t incompatible_features;
+  int r = cls_client::get_features(&io_ctx, util::header_name(image_id), true,
+                                   &features, &incompatible_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<I>::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
+
 template <typename I>
 int Trash<I>::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
                    const std::string &image_name, uint64_t delay) {
@@ -75,6 +164,11 @@ int Trash<I>::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
     return -EINVAL;
   }
 
+  r = disable_mirroring<I>(ictx);
+  if (r < 0) {
+    return r;
+  }
+
   utime_t delete_time{ceph_clock_now()};
   utime_t deferment_end_time{delete_time};
   deferment_end_time += delay;
@@ -324,7 +418,7 @@ int Trash<I>::restore(librados::IoCtx &io_ctx, const std::string &image_id,
     }
   }
 
-  ldout(cct, 2) << "adding rbd image from v2 directory..." << dendl;
+  ldout(cct, 2) << "adding rbd image to v2 directory..." << dendl;
   r = cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, image_name,
                                 image_id);
   if (r < 0 && r != -EEXIST) {
@@ -333,6 +427,11 @@ int Trash<I>::restore(librados::IoCtx &io_ctx, const std::string &image_id,
     return r;
   }
 
+  r = enable_mirroring<I>(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 245f81943cbb52a1701c8a29b3e7c1713f059172..4b2211e24daf31f3a14b4241a3046628452139cc 100644 (file)
@@ -276,6 +276,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"));
 
@@ -632,6 +671,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);