]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: explicitly specify mode on mirror image enable
authorMykola Golub <mgolub@suse.com>
Thu, 12 Dec 2019 14:38:08 +0000 (14:38 +0000)
committerMykola Golub <mgolub@suse.com>
Mon, 16 Dec 2019 08:24:30 +0000 (08:24 +0000)
- don't use journaling feature to chose the mode;
- provide new API function mirror_image_enable2;
- return back the old behavior to automatically enable/disable
  journaling feature on enabling/disabling image mirroring.

Signed-off-by: Mykola Golub <mgolub@suse.com>
24 files changed:
qa/workunits/rbd/rbd_mirror.sh
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/api/Migration.cc
src/librbd/api/Migration.h
src/librbd/api/Mirror.cc
src/librbd/api/Mirror.h
src/librbd/api/Trash.cc
src/librbd/image/CloneRequest.cc
src/librbd/image/CreateRequest.cc
src/librbd/librbd.cc
src/librbd/mirror/EnableRequest.cc
src/librbd/mirror/EnableRequest.h
src/librbd/operation/EnableFeaturesRequest.cc
src/librbd/operation/EnableFeaturesRequest.h
src/pybind/rbd/rbd.pyx
src/test/librbd/image/test_mock_CloneRequest.cc
src/test/librbd/operation/test_mock_DisableFeaturesRequest.cc
src/test/librbd/operation/test_mock_EnableFeaturesRequest.cc
src/test/librbd/test_Migration.cc
src/test/librbd/test_mirroring.cc
src/test/pybind/test_rbd.py
src/test/rbd_mirror/test_ImageReplayer.cc
src/test/rbd_mirror/test_PoolWatcher.cc

index 86af089f8a55968d7cb62c30ce3a4049cfb47093..cf0d9f7e300e8883a3ac932092dbd441696a378b 100755 (executable)
@@ -334,6 +334,7 @@ done
 
 set_pool_mirror_mode ${CLUSTER2} ${POOL} 'pool'
 for i in ${image2} ${image4}; do
+  enable_journaling ${CLUSTER2} ${POOL} ${i}
   wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'present'
   wait_for_snap_present ${CLUSTER1} ${POOL} ${i} 'snap2'
   wait_for_image_replay_started ${CLUSTER1} ${POOL} ${i}
@@ -389,6 +390,7 @@ fi
 start_mirrors ${CLUSTER1}
 wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted'
 set_pool_mirror_mode ${CLUSTER2} ${POOL} 'pool'
+enable_journaling ${CLUSTER2} ${POOL} ${image}
 wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
 wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
 
index a53e2c448fb78ea9d3af0e3a74610a6f8d96033e..7cf5ca9d241363f61efbd5967888c3edffba9fba 100644 (file)
@@ -1180,7 +1180,9 @@ CEPH_RBD_API int rbd_metadata_list(rbd_image_t image, const char *start, uint64_
     char *keys, size_t *key_len, char *values, size_t *vals_len);
 
 // RBD image mirroring support functions
-CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image);
+CEPH_RBD_API int rbd_mirror_image_enable(rbd_image_t image) CEPH_RBD_DEPRECATED;
+CEPH_RBD_API int rbd_mirror_image_enable2(rbd_image_t image,
+                                          rbd_mirror_image_mode_t mode);
 CEPH_RBD_API int rbd_mirror_image_disable(rbd_image_t image, bool force);
 CEPH_RBD_API int rbd_mirror_image_promote(rbd_image_t image, bool force);
 CEPH_RBD_API int rbd_mirror_image_demote(rbd_image_t image);
index e53495e18427ff82865b1d721935043a26979b1d..f5f304c94bd74677675a7b4262458eb9a0e8d501 100644 (file)
@@ -728,7 +728,8 @@ public:
   int metadata_list(const std::string &start, uint64_t max, std::map<std::string, ceph::bufferlist> *pairs);
 
   // RBD image mirroring support functions
-  int mirror_image_enable();
+  int mirror_image_enable() CEPH_RBD_DEPRECATED;
+  int mirror_image_enable2(mirror_image_mode_t mode);
   int mirror_image_disable(bool force);
   int mirror_image_promote(bool force);
   int mirror_image_demote();
index 138569961827a715a2b7de95c70d4cd9c285054c..4d9cfb8b4c4fbb903200f3f526c29d2211d2db3c 100644 (file)
@@ -186,6 +186,7 @@ int open_source_image(librados::IoCtx& io_ctx, const std::string &image_name,
                       I **src_image_ctx, librados::IoCtx *dst_io_ctx,
                       std::string *dst_image_name, std::string *dst_image_id,
                       bool *flatten, bool *mirroring,
+                      cls::rbd::MirrorImageMode *mirror_image_mode,
                       cls::rbd::MigrationState *state,
                       std::string *state_description) {
   CephContext* cct = reinterpret_cast<CephContext *>(io_ctx.cct());
@@ -328,6 +329,7 @@ int open_source_image(librados::IoCtx& io_ctx, const std::string &image_name,
   *dst_image_id = migration_spec.image_id;
   *flatten = migration_spec.flatten;
   *mirroring = migration_spec.mirroring;
+  *mirror_image_mode = migration_spec.mirror_image_mode;
   *state = migration_spec.state;
   *state_description = migration_spec.state_description;
 
@@ -426,8 +428,9 @@ int Migration<I>::prepare(librados::IoCtx& io_ctx,
 
   ldout(cct, 20) << "updated opts=" << opts << dendl;
 
-  Migration migration(image_ctx, dest_io_ctx, dest_image_name, "", opts, flatten > 0,
-                      false, cls::rbd::MIGRATION_STATE_PREPARING, "", nullptr);
+  Migration migration(image_ctx, dest_io_ctx, dest_image_name, "", opts,
+                      flatten > 0, false, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                      cls::rbd::MIGRATION_STATE_PREPARING, "", nullptr);
   r = migration.prepare();
 
   features &= ~RBD_FEATURE_MIGRATING;
@@ -450,12 +453,14 @@ int Migration<I>::execute(librados::IoCtx& io_ctx,
   std::string dest_image_id;
   bool flatten;
   bool mirroring;
+  cls::rbd::MirrorImageMode mirror_image_mode;
   cls::rbd::MigrationState state;
   std::string state_description;
 
   int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
                             &dest_image_name, &dest_image_id, &flatten,
-                            &mirroring, &state, &state_description);
+                            &mirroring, &mirror_image_mode, &state,
+                            &state_description);
   if (r < 0) {
     return r;
   }
@@ -476,8 +481,8 @@ int Migration<I>::execute(librados::IoCtx& io_ctx,
 
   ImageOptions opts;
   Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
-                      opts, flatten, mirroring, state, state_description,
-                      &prog_ctx);
+                      opts, flatten, mirroring, mirror_image_mode, state,
+                      state_description, &prog_ctx);
   r = migration.execute();
   if (r < 0) {
     return r;
@@ -499,12 +504,14 @@ int Migration<I>::abort(librados::IoCtx& io_ctx, const std::string &image_name,
   std::string dest_image_id;
   bool flatten;
   bool mirroring;
+  cls::rbd::MirrorImageMode mirror_image_mode;
   cls::rbd::MigrationState state;
   std::string state_description;
 
   int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
                             &dest_image_name, &dest_image_id, &flatten,
-                            &mirroring, &state, &state_description);
+                            &mirroring, &mirror_image_mode, &state,
+                            &state_description);
   if (r < 0) {
     return r;
   }
@@ -516,8 +523,8 @@ int Migration<I>::abort(librados::IoCtx& io_ctx, const std::string &image_name,
 
   ImageOptions opts;
   Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
-                      opts, flatten, mirroring, state, state_description,
-                      &prog_ctx);
+                      opts, flatten, mirroring, mirror_image_mode, state,
+                      state_description, &prog_ctx);
   r = migration.abort();
 
   image_ctx->state->close();
@@ -543,12 +550,14 @@ int Migration<I>::commit(librados::IoCtx& io_ctx,
   std::string dest_image_id;
   bool flatten;
   bool mirroring;
+  cls::rbd::MirrorImageMode mirror_image_mode;
   cls::rbd::MigrationState state;
   std::string state_description;
 
   int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
                             &dest_image_name, &dest_image_id, &flatten,
-                            &mirroring, &state, &state_description);
+                            &mirroring, &mirror_image_mode, &state,
+                            &state_description);
   if (r < 0) {
     return r;
   }
@@ -566,8 +575,8 @@ int Migration<I>::commit(librados::IoCtx& io_ctx,
 
   ImageOptions opts;
   Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
-                      opts, flatten, mirroring, state, state_description,
-                      &prog_ctx);
+                      opts, flatten, mirroring, mirror_image_mode, state,
+                      state_description, &prog_ctx);
   r = migration.commit();
 
   // image_ctx is closed in commit when removing src image
@@ -593,12 +602,14 @@ int Migration<I>::status(librados::IoCtx& io_ctx,
   std::string dest_image_id;
   bool flatten;
   bool mirroring;
+  cls::rbd::MirrorImageMode mirror_image_mode;
   cls::rbd::MigrationState state;
   std::string state_description;
 
   int r = open_source_image(io_ctx, image_name, &image_ctx, &dest_io_ctx,
                             &dest_image_name, &dest_image_id, &flatten,
-                            &mirroring, &state, &state_description);
+                            &mirroring, &mirror_image_mode, &state,
+                            &state_description);
   if (r < 0) {
     return r;
   }
@@ -609,8 +620,8 @@ int Migration<I>::status(librados::IoCtx& io_ctx,
 
   ImageOptions opts;
   Migration migration(image_ctx, dest_io_ctx, dest_image_name, dest_image_id,
-                      opts, flatten, mirroring, state, state_description,
-                      nullptr);
+                      opts, flatten, mirroring, mirror_image_mode, state,
+                      state_description, nullptr);
   r = migration.status(status);
 
   image_ctx->state->close();
@@ -627,6 +638,7 @@ Migration<I>::Migration(I *src_image_ctx, librados::IoCtx& dst_io_ctx,
                         const std::string &dstname,
                         const std::string &dst_image_id,
                         ImageOptions& opts, bool flatten, bool mirroring,
+                        cls::rbd::MirrorImageMode mirror_image_mode,
                         cls::rbd::MigrationState state,
                         const std::string &state_description,
                         ProgressContext *prog_ctx)
@@ -639,16 +651,18 @@ Migration<I>::Migration(I *src_image_ctx, librados::IoCtx& dst_io_ctx,
     m_dst_image_id(dst_image_id.empty() ?
                    util::generate_image_id(m_dst_io_ctx) : dst_image_id),
     m_dst_header_oid(util::header_name(m_dst_image_id)), m_image_options(opts),
-    m_flatten(flatten), m_mirroring(mirroring), m_prog_ctx(prog_ctx),
+    m_flatten(flatten), m_mirroring(mirroring),
+    m_mirror_image_mode(mirror_image_mode), m_prog_ctx(prog_ctx),
     m_src_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_SRC,
                          m_dst_io_ctx.get_id(), m_dst_io_ctx.get_namespace(),
-                         m_dst_image_name, m_dst_image_id, {}, 0, flatten,
-                         mirroring, state, state_description),
+                         m_dst_image_name, m_dst_image_id, {}, 0, mirroring,
+                         mirror_image_mode, flatten, state, state_description),
     m_dst_migration_spec(cls::rbd::MIGRATION_HEADER_TYPE_DST,
                          src_image_ctx->md_ctx.get_id(),
                          src_image_ctx->md_ctx.get_namespace(),
                          m_src_image_ctx->name, m_src_image_ctx->id, {}, 0,
-                         flatten, mirroring, state, state_description) {
+                         mirroring, mirror_image_mode, flatten, state,
+                         state_description) {
   m_src_io_ctx.dup(src_image_ctx->md_ctx);
 }
 
@@ -661,21 +675,21 @@ int Migration<I>::prepare() {
     return r;
   }
 
-  r = disable_mirroring(m_src_image_ctx, &m_mirroring);
+  r = disable_mirroring(m_src_image_ctx, &m_mirroring, &m_mirror_image_mode);
   if (r < 0) {
     return r;
   }
 
   r = unlink_src_image();
   if (r < 0) {
-    enable_mirroring(m_src_image_ctx, m_mirroring);
+    enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
     return r;
   }
 
   r = set_migration();
   if (r < 0) {
     relink_src_image();
-    enable_mirroring(m_src_image_ctx, m_mirroring);
+    enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
     return r;
   }
 
@@ -857,7 +871,7 @@ int Migration<I>::abort() {
     return r;
   }
 
-  r = enable_mirroring(m_src_image_ctx, m_mirroring);
+  r = enable_mirroring(m_src_image_ctx, m_mirroring, m_mirror_image_mode);
   if (r < 0) {
     return r;
   }
@@ -900,7 +914,7 @@ int Migration<I>::commit() {
     return r;
   }
 
-  r = enable_mirroring(dst_image_ctx, m_mirroring);
+  r = enable_mirroring(dst_image_ctx, m_mirroring, m_mirror_image_mode);
   if (r < 0) {
     return r;
   }
@@ -1295,7 +1309,7 @@ int Migration<I>::create_dst_image() {
   m_dst_migration_spec = {cls::rbd::MIGRATION_HEADER_TYPE_DST,
                           m_src_io_ctx.get_id(), m_src_io_ctx.get_namespace(),
                           m_src_image_name, m_src_image_id, snap_seqs, size,
-                          m_flatten, m_mirroring,
+                          m_mirroring, m_mirror_image_mode, m_flatten,
                           cls::rbd::MIGRATION_STATE_PREPARING, ""};
 
   r = cls_client::migration_set(&m_dst_io_ctx, m_dst_header_oid,
@@ -1414,7 +1428,9 @@ int Migration<I>::update_group(I *from_image_ctx, I *to_image_ctx) {
 }
 
 template <typename I>
-int Migration<I>::disable_mirroring(I *image_ctx, bool *was_enabled) {
+int Migration<I>::disable_mirroring(
+    I *image_ctx, bool *was_enabled,
+    cls::rbd::MirrorImageMode *mirror_image_mode) {
   *was_enabled = false;
 
   cls::rbd::MirrorImage mirror_image;
@@ -1433,6 +1449,7 @@ int Migration<I>::disable_mirroring(I *image_ctx, bool *was_enabled) {
 
   if (mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
     *was_enabled = true;
+    *mirror_image_mode = mirror_image.mode;
   }
 
   ldout(m_cct, 10) << dendl;
@@ -1453,7 +1470,9 @@ int Migration<I>::disable_mirroring(I *image_ctx, bool *was_enabled) {
 }
 
 template <typename I>
-int Migration<I>::enable_mirroring(I *image_ctx, bool was_enabled) {
+int Migration<I>::enable_mirroring(
+    I *image_ctx, bool was_enabled,
+    cls::rbd::MirrorImageMode mirror_image_mode) {
   cls::rbd::MirrorMode mirror_mode;
   int r = cls_client::mirror_mode_get(&image_ctx->md_ctx, &mirror_mode);
   if (r < 0 && r != -ENOENT) {
@@ -1475,9 +1494,10 @@ int Migration<I>::enable_mirroring(I *image_ctx, bool was_enabled) {
   ldout(m_cct, 10) << dendl;
 
   C_SaferCond ctx;
-  auto req = mirror::EnableRequest<I>::create(image_ctx->md_ctx, image_ctx->id,
-                                              "", image_ctx->op_work_queue,
-                                              &ctx);
+  auto req = mirror::EnableRequest<I>::create(
+    image_ctx->md_ctx, image_ctx->id,
+    static_cast<mirror_image_mode_t>(mirror_image_mode), "",
+    image_ctx->op_work_queue, &ctx);
   req->send();
   r = ctx.wait();
   if (r < 0) {
index 4261eea5815ddb86711c172cb0fc0c9341f6a8c0..d87f49407650894bc8c695ba37557ac8875b571f 100644 (file)
@@ -47,6 +47,7 @@ private:
   ImageOptions &m_image_options;
   bool m_flatten;
   bool m_mirroring;
+  cls::rbd::MirrorImageMode m_mirror_image_mode;
   ProgressContext *m_prog_ctx;
 
   cls::rbd::MigrationSpec m_src_migration_spec;
@@ -55,6 +56,7 @@ private:
   Migration(ImageCtxT *image_ctx, librados::IoCtx& dest_io_ctx,
             const std::string &dest_image_name, const std::string &dst_image_id,
             ImageOptions& opts, bool flatten, bool mirroring,
+            cls::rbd::MirrorImageMode mirror_image_mode,
             cls::rbd::MigrationState state, const std::string &state_desc,
             ProgressContext *prog_ctx);
 
@@ -68,8 +70,10 @@ private:
 
   int list_src_snaps(std::vector<librbd::snap_info_t> *snaps);
   int validate_src_snaps();
-  int disable_mirroring(ImageCtxT *image_ctx, bool *was_enabled);
-  int enable_mirroring(ImageCtxT *image_ctx, bool was_enabled);
+  int disable_mirroring(ImageCtxT *image_ctx, bool *was_enabled,
+                        cls::rbd::MirrorImageMode *mirror_image_mode);
+  int enable_mirroring(ImageCtxT *image_ctx, bool was_enabled,
+                       cls::rbd::MirrorImageMode mirror_image_mode);
   int set_migration();
   int unlink_src_image();
   int relink_src_image();
index 8fb822a18bebfddf6d9ea917a5506252d7334285..decafb7f825ed98c996777c54f8fbc1a6a35d942 100644 (file)
@@ -351,9 +351,12 @@ struct C_ImageGetGlobalStatus : public C_ImageGetInfo {
 } // anonymous namespace
 
 template <typename I>
-int Mirror<I>::image_enable(I *ictx, bool relax_same_pool_parent_check) {
+int Mirror<I>::image_enable(I *ictx, mirror_image_mode_t mode,
+                            bool relax_same_pool_parent_check) {
   CephContext *cct = ictx->cct;
-  ldout(cct, 20) << "ictx=" << ictx << dendl;
+  ldout(cct, 20) << "ictx=" << ictx << " mode=" << mode
+                 << " relax_same_pool_parent_check="
+                 << relax_same_pool_parent_check <<  dendl;
 
   int r = ictx->state->refresh_if_required();
   if (r < 0) {
@@ -392,8 +395,21 @@ int Mirror<I>::image_enable(I *ictx, bool relax_same_pool_parent_check) {
     }
   }
 
+  if (mode == RBD_MIRROR_IMAGE_MODE_JOURNAL &&
+      !ictx->test_features(RBD_FEATURE_JOURNALING)) {
+    uint64_t features = RBD_FEATURE_JOURNALING;
+    if (!ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
+      features |= RBD_FEATURE_EXCLUSIVE_LOCK;
+    }
+    r = ictx->operations->update_features(features, true);
+    if (r < 0) {
+      lderr(cct) << "cannot enable journaling: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+  }
+
   C_SaferCond ctx;
-  auto req = mirror::EnableRequest<ImageCtx>::create(ictx, &ctx);
+  auto req = mirror::EnableRequest<ImageCtx>::create(ictx, mode, &ctx);
   req->send();
 
   r = ctx.wait();
@@ -529,6 +545,14 @@ int Mirror<I>::image_disable(I *ictx, bool force) {
       rollback = true;
       return r;
     }
+
+    if (mirror_image_internal.mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
+      r = ictx->operations->update_features(RBD_FEATURE_JOURNALING, false);
+      if (r < 0) {
+        lderr(cct) << "cannot disable journaling: " << cpp_strerror(r) << dendl;
+        // not fatal
+      }
+    }
   }
 
   return 0;
@@ -903,7 +927,7 @@ int Mirror<I>::mode_set(librados::IoCtx& io_ctx,
           return r;
         }
 
-        r = image_enable(img_ctx, true);
+        r = image_enable(img_ctx, RBD_MIRROR_IMAGE_MODE_JOURNAL, true);
         int close_r = img_ctx->state->close();
         if (r < 0) {
           lderr(cct) << "error enabling mirroring for image "
index c26c88d4b213b0dc97e4504297ce4e297e9e2ffc..949cb136d182cf4ab13c4b73a696cb851db3a068 100644 (file)
@@ -69,7 +69,8 @@ struct Mirror {
                                     size_t max,
                                     std::map<std::string, std::string> *ids);
 
-  static int image_enable(ImageCtxT *ictx, bool relax_same_pool_parent_check);
+  static int image_enable(ImageCtxT *ictx, mirror_image_mode_t mode,
+                          bool relax_same_pool_parent_check);
   static int image_disable(ImageCtxT *ictx, bool force);
   static int image_promote(ImageCtxT *ictx, bool force);
   static void image_promote(ImageCtxT *ictx, bool force, Context *on_finish);
index d37d3300579c1fb177d2fdbfb9b4e04373874180..8287fdb3506d0b44f97148982b20ebf41129f42f 100644 (file)
@@ -84,6 +84,10 @@ int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) {
     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) {
@@ -103,7 +107,8 @@ int enable_mirroring(IoCtx &io_ctx, const std::string &image_id) {
   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, "",
+  auto req = mirror::EnableRequest<I>::create(io_ctx, image_id,
+                                              RBD_MIRROR_IMAGE_MODE_JOURNAL, "",
                                               op_work_queue, &ctx);
   req->send();
   r = ctx.wait();
index 3a4e7c0bde60847113feaa94f00e85c03b4f5048..75b52f5785a0f0e5420433dc6ef5bb2bb79a8a3d 100644 (file)
@@ -526,9 +526,11 @@ void CloneRequest<I>::enable_mirror() {
   Context *ctx = create_context_callback<
     klass, &klass::handle_enable_mirror>(this);
 
+  // TODO: in future rbd-mirror will want to enable mirroring
+  // not only in journal mode.
   mirror::EnableRequest<I> *req = mirror::EnableRequest<I>::create(
-    m_imctx->md_ctx, m_id, m_non_primary_global_image_id,
-    m_imctx->op_work_queue, ctx);
+    m_imctx->md_ctx, m_id, RBD_MIRROR_IMAGE_MODE_JOURNAL,
+    m_non_primary_global_image_id, m_imctx->op_work_queue, ctx);
   req->send();
 }
 
index 44428868ad5d1aa1d4a6f02d0b02705e3be20b1c..400296f5efb0a97e8e576f96fba58176fb5c7b6b 100644 (file)
@@ -655,7 +655,11 @@ void CreateRequest<I>::mirror_image_enable() {
   ldout(m_cct, 15) << dendl;
   auto ctx = create_context_callback<
     CreateRequest<I>, &CreateRequest<I>::handle_mirror_image_enable>(this);
+
+  // TODO: in future rbd-mirror will want to enable mirroring
+  // not only in journal mode.
   auto req = mirror::EnableRequest<I>::create(m_io_ctx, m_image_id,
+                                              RBD_MIRROR_IMAGE_MODE_JOURNAL,
                                               m_non_primary_global_image_id,
                                               m_op_work_queue, ctx);
   req->send();
index 517fa4132dcdcdcb0523a60dc3d334315619a7e4..2d1708586baa7f02176084184b902574b51ea07d 100644 (file)
@@ -2785,8 +2785,12 @@ namespace librbd {
   }
 
   int Image::mirror_image_enable() {
+    return mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
+  }
+
+  int Image::mirror_image_enable2(mirror_image_mode_t mode) {
     ImageCtx *ictx = (ImageCtx *)ctx;
-    return librbd::api::Mirror<>::image_enable(ictx, false);
+    return librbd::api::Mirror<>::image_enable(ictx, mode, false);
   }
 
   int Image::mirror_image_disable(bool force) {
@@ -6152,9 +6156,15 @@ extern "C" int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t
 }
 
 extern "C" int rbd_mirror_image_enable(rbd_image_t image)
+{
+  return rbd_mirror_image_enable2(image, RBD_MIRROR_IMAGE_MODE_JOURNAL);
+}
+
+extern "C" int rbd_mirror_image_enable2(rbd_image_t image,
+                                        rbd_mirror_image_mode_t mode)
 {
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
-  return librbd::api::Mirror<>::image_enable(ictx, false);
+  return librbd::api::Mirror<>::image_enable(ictx, mode, false);
 }
 
 extern "C" int rbd_mirror_image_disable(rbd_image_t image, bool force)
index c94ad43bd59d146f31991c91bf9e5f338ea61294..beea237038fcdd176d567918f00cc32ef0ffede5 100644 (file)
@@ -23,9 +23,11 @@ using util::create_rados_callback;
 template <typename I>
 EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
                                 const std::string &image_id,
+                                mirror_image_mode_t mode,
                                 const std::string &non_primary_global_image_id,
                                 ContextWQ *op_work_queue, Context *on_finish)
   : m_io_ctx(io_ctx), m_image_id(image_id),
+    m_mode(static_cast<cls::rbd::MirrorImageMode>(mode)),
     m_non_primary_global_image_id(non_primary_global_image_id),
     m_op_work_queue(op_work_queue), m_on_finish(on_finish),
     m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())) {
@@ -62,7 +64,10 @@ Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
   }
 
   if (*result == 0) {
-    if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+    if (m_mirror_image.mode != m_mode) {
+      lderr(m_cct) << "invalid current image mirror mode" << dendl;
+      *result = -EINVAL;
+    } else if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
       ldout(m_cct, 10) << this << " " << __func__
                        << ": mirroring is already enabled" << dendl;
     } else {
@@ -79,6 +84,7 @@ Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
   }
 
   *result = 0;
+  m_mirror_image.mode = m_mode;
   if (m_non_primary_global_image_id.empty()) {
     uuid_d uuid_gen;
     uuid_gen.generate_random();
@@ -86,49 +92,6 @@ Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
   } else {
     m_mirror_image.global_image_id = m_non_primary_global_image_id;
   }
-
-  send_get_features();
-  return nullptr;
-}
-
-template <typename I>
-void EnableRequest<I>::send_get_features() {
-  ldout(m_cct, 10) << this << " " << __func__ << dendl;
-
-  librados::ObjectReadOperation op;
-  cls_client::get_features_start(&op, true);
-
-  using klass = EnableRequest<I>;
-  librados::AioCompletion *comp =
-    create_rados_callback<klass, &klass::handle_get_features>(this);
-  m_out_bl.clear();
-  int r = m_io_ctx.aio_operate(util::header_name(m_image_id), comp, &op,
-                               &m_out_bl);
-  ceph_assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-Context *EnableRequest<I>::handle_get_features(int *result) {
-  ldout(m_cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
-
-  uint64_t features, incompatible_features;
-  if (*result == 0) {
-    auto iter = m_out_bl.cbegin();
-    *result = cls_client::get_features_finish(&iter, &features,
-                                              &incompatible_features);
-  }
-
-  if (*result != 0) {
-    lderr(m_cct) << "failed to retrieve image features: "
-                 << cpp_strerror(*result) << dendl;
-    return m_on_finish;
-  }
-
-  // TODO: be explicit about the image mirror mode
-
-  m_mirror_image.mode = (features & RBD_FEATURE_JOURNALING) != 0 ?
-    cls::rbd::MIRROR_IMAGE_MODE_JOURNAL : cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT;
   m_mirror_image.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
 
   send_get_tag_owner();
index 66b0c1f6859ff30cfa169f880f6a945842094479..9fa3c63304c1134f9c9eca48b23acdc6a701dc80 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "include/buffer_fwd.h"
 #include "include/rados/librados_fwd.hpp"
+#include "include/rbd/librbd.hpp"
 #include "cls/rbd/cls_rbd_types.h"
 #include <map>
 #include <string>
@@ -22,16 +23,19 @@ namespace mirror {
 template <typename ImageCtxT = ImageCtx>
 class EnableRequest {
 public:
-  static EnableRequest *create(ImageCtxT *image_ctx, Context *on_finish) {
-    return create(image_ctx->md_ctx, image_ctx->id, "",
+  static EnableRequest *create(ImageCtxT *image_ctx, mirror_image_mode_t mode,
+                               Context *on_finish) {
+    return create(image_ctx->md_ctx, image_ctx->id, mode, "",
                   image_ctx->op_work_queue, on_finish);
   }
   static EnableRequest *create(librados::IoCtx &io_ctx,
                                const std::string &image_id,
+                               mirror_image_mode_t mode,
                                const std::string &non_primary_global_image_id,
                                ContextWQ *op_work_queue, Context *on_finish) {
-    return new EnableRequest(io_ctx, image_id, non_primary_global_image_id,
-                             op_work_queue, on_finish);
+    return new EnableRequest(io_ctx, image_id, mode,
+                             non_primary_global_image_id, op_work_queue,
+                             on_finish);
   }
 
   void send();
@@ -46,9 +50,6 @@ private:
    * GET_MIRROR_IMAGE * * * * * * *
    *    |                         * (on error)
    *    v                         *
-   * GET_FEATURES * * * * * * * * *
-   *    |                         *
-   *    v                         *
    * GET_TAG_OWNER  * * * * * * * *
    *    |  (skip if not needed)   *
    *    v                         *
@@ -64,11 +65,13 @@ private:
    */
 
   EnableRequest(librados::IoCtx &io_ctx, const std::string &image_id,
+                mirror_image_mode_t mode,
                 const std::string &non_primary_global_image_id,
                 ContextWQ *op_work_queue, Context *on_finish);
 
   librados::IoCtx &m_io_ctx;
   std::string m_image_id;
+  cls::rbd::MirrorImageMode m_mode;
   std::string m_non_primary_global_image_id;
   ContextWQ *m_op_work_queue;
   Context *m_on_finish;
index c85c56f86d41a0cd7bb33133cb3efe462f8e7a02..dd4eadfacd485931e00f68824b583798457e1c47 100644 (file)
@@ -12,7 +12,6 @@
 #include "librbd/image/SetFlagsRequest.h"
 #include "librbd/io/ImageRequestWQ.h"
 #include "librbd/journal/CreateRequest.h"
-#include "librbd/mirror/DisableRequest.h"
 #include "librbd/mirror/EnableRequest.h"
 #include "librbd/object_map/CreateRequest.h"
 
@@ -119,7 +118,10 @@ void EnableFeaturesRequest<I>::send_get_mirror_mode() {
   CephContext *cct = image_ctx.cct;
 
   if ((m_features & RBD_FEATURE_JOURNALING) == 0) {
-    send_get_mirror_image();
+    Context *ctx = create_context_callback<
+      EnableFeaturesRequest<I>,
+      &EnableFeaturesRequest<I>::handle_get_mirror_mode>(this);
+    ctx->complete(-ENOENT);
     return;
   }
 
@@ -143,9 +145,10 @@ Context *EnableFeaturesRequest<I>::handle_get_mirror_mode(int *result) {
   CephContext *cct = image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": r=" << *result << dendl;
 
+  cls::rbd::MirrorMode mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
   if (*result == 0) {
     auto it = m_out_bl.cbegin();
-    *result = cls_client::mirror_mode_get_finish(&it, &m_mirror_mode);
+    *result = cls_client::mirror_mode_get_finish(&it, &mirror_mode);
   } else if (*result == -ENOENT) {
     *result = 0;
   }
@@ -156,67 +159,7 @@ Context *EnableFeaturesRequest<I>::handle_get_mirror_mode(int *result) {
     return handle_finish(*result);
   }
 
-  if (m_mirror_mode == cls::rbd::MIRROR_MODE_POOL) {
-    m_enable_mirroring = true;
-  }
-
-  send_get_mirror_image();
-  return nullptr;
-}
-
-template <typename I>
-void EnableFeaturesRequest<I>::send_get_mirror_image() {
-  I &image_ctx = this->m_image_ctx;
-  CephContext *cct = image_ctx.cct;
-
-  if (m_mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) {
-    Context *ctx = create_context_callback<
-      EnableFeaturesRequest<I>,
-      &EnableFeaturesRequest<I>::handle_get_mirror_image>(this);
-    ctx->complete(-ENOENT);
-    return;
-  }
-
-  ldout(cct, 20) << this << " " << __func__ << dendl;
-
-  librados::ObjectReadOperation op;
-  cls_client::mirror_image_get_start(&op, image_ctx.id);
-
-  using klass = EnableFeaturesRequest<I>;
-  librados::AioCompletion *comp =
-    create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
-  m_out_bl.clear();
-  int r = image_ctx.md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
-  ceph_assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-Context *EnableFeaturesRequest<I>::handle_get_mirror_image(int *result) {
-  I &image_ctx = this->m_image_ctx;
-  CephContext *cct = image_ctx.cct;
-  ldout(cct, 20) << this << " " << __func__ << ": r=" << *result << dendl;
-
-  cls::rbd::MirrorImage mirror_image;
-  if (*result == 0) {
-    auto it = m_out_bl.cbegin();
-    *result = cls_client::mirror_image_get_finish(&it, &mirror_image);
-  } else if (*result == -ENOENT) {
-    *result = 0;
-  }
-
-  if (*result < 0) {
-    lderr(cct) << "failed to retrieve mirror image info: "
-               << cpp_strerror(*result) << dendl;
-    return handle_finish(*result);
-  }
-
-  if (mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
-    lderr(cct) << "cannot enable journaling: image snapshot mirroring enabled"
-               << dendl;
-    *result = -EINVAL;
-    return handle_finish(*result);
-  }
+  m_enable_mirroring = (mirror_mode == cls::rbd::MIRROR_MODE_POOL);
 
   bool create_journal = false;
   do {
@@ -477,8 +420,8 @@ void EnableFeaturesRequest<I>::send_enable_mirror_image() {
     EnableFeaturesRequest<I>,
     &EnableFeaturesRequest<I>::handle_enable_mirror_image>(this);
 
-  mirror::EnableRequest<I> *req =
-    mirror::EnableRequest<I>::create(&image_ctx, ctx);
+  mirror::EnableRequest<I> *req = mirror::EnableRequest<I>::create(
+    &image_ctx, RBD_MIRROR_IMAGE_MODE_JOURNAL, ctx);
   req->send();
 }
 
index d1bfe4ad4241b04fa165edf0093a616243c8135f..1c91b4dc72a2304598afdac61cd8d1e093d3beae 100644 (file)
@@ -4,8 +4,6 @@
 #ifndef CEPH_LIBRBD_OPERATION_ENABLE_FEATURES_REQUEST_H
 #define CEPH_LIBRBD_OPERATION_ENABLE_FEATURES_REQUEST_H
 
-#include "cls/rbd/cls_rbd_types.h"
-
 #include "librbd/operation/Request.h"
 
 class Context;
@@ -54,11 +52,8 @@ private:
    * STATE_BLOCK_WRITES
    *    |
    *    v
-   * STATE_GET_MIRROR_MODE (skip if not
-   *    |                   enabling journaling)
-   *    v
-   * STATE_GET_MIRROR_IMAGE (skip if mirror mode
-   *    |                    is not IMAGE)
+   * STATE_GET_MIRROR_MODE
+   *    |
    *    v
    * STATE_CREATE_JOURNAL (skip if not
    *    |                  required)
@@ -75,9 +70,9 @@ private:
    * STATE_CREATE_OBJECT_MAP (skip if not
    *    |                     required)
    *    v
-   * STATE_ENABLE_MIRROR_IMAGE (skip if not
-   *    |                       required)
-   *    v
+   * STATE_ENABLE_MIRROR_IMAGE
+   *    |
+   *    V
    * STATE_NOTIFY_UPDATE
    *    |
    *    | (unblock writes)
@@ -87,8 +82,6 @@ private:
    *
    */
 
-  cls::rbd::MirrorMode m_mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
-
   uint64_t m_features;
 
   bool m_enable_mirroring = false;
@@ -110,9 +103,6 @@ private:
   void send_get_mirror_mode();
   Context *handle_get_mirror_mode(int *result);
 
-  void send_get_mirror_image();
-  Context *handle_get_mirror_image(int *result);
-
   void send_create_journal();
   Context *handle_create_journal(int *result);
 
index 6544bfbdf15bf64a78dca6a51ed78882f72163fe..99699c4cf3342260231eb0c1019c3a1eb9722e65 100644 (file)
@@ -582,7 +582,8 @@ cdef extern from "rbd/librbd.h" nogil:
     int rbd_flush(rbd_image_t image)
     int rbd_invalidate_cache(rbd_image_t image)
 
-    int rbd_mirror_image_enable(rbd_image_t image)
+    int rbd_mirror_image_enable2(rbd_image_t image,
+                                 rbd_mirror_image_mode_t mode)
     int rbd_mirror_image_disable(rbd_image_t image, bint force)
     int rbd_mirror_image_promote(rbd_image_t image, bint force)
     int rbd_mirror_image_demote(rbd_image_t image)
@@ -4509,12 +4510,13 @@ written." % (self.name, ret, length))
         if ret < 0:
             raise make_ex(ret, 'error unlocking image')
 
-    def mirror_image_enable(self):
+    def mirror_image_enable(self, mode=RBD_MIRROR_IMAGE_MODE_JOURNAL):
         """
         Enable mirroring for the image.
         """
+        cdef rbd_mirror_image_mode_t c_mode = mode
         with nogil:
-            ret = rbd_mirror_image_enable(self.image)
+            ret = rbd_mirror_image_enable2(self.image, c_mode)
         if ret < 0:
             raise make_ex(ret, 'error enabling mirroring for image %s' % self.name)
 
index fd63ded44778f2053d0fc2f88f688aeb97d25ca5..009e4c4859e27da0d35d6340b0b4940225b512d7 100644 (file)
@@ -160,6 +160,7 @@ struct EnableRequest<MockTestImageCtx> {
   static EnableRequest* s_instance;
   static EnableRequest* create(librados::IoCtx &io_ctx,
                                const std::string &image_id,
+                               mirror_image_mode_t mode,
                                const std::string &non_primary_global_image_id,
                                MockContextWQ *op_work_queue,
                                Context *on_finish) {
index 78977ae76555afdc02b159b10501768082784a88..ec374d518e96adb033f93d3f882904129062bfc4 100644 (file)
@@ -6,7 +6,6 @@
 #include "test/librbd/mock/MockImageCtx.h"
 #include "test/librbd/mock/MockJournalPolicy.h"
 #include "cls/rbd/cls_rbd_client.h"
-#include "librbd/api/Mirror.h"
 #include "librbd/internal.h"
 #include "librbd/image/SetFlagsRequest.h"
 #include "librbd/io/AioCompletion.h"
@@ -434,7 +433,7 @@ TEST_F(TestMockOperationDisableFeaturesRequest, ObjectMapError) {
   ASSERT_EQ(-EINVAL, cond_ctx.wait());
 }
 
-TEST_F(TestMockOperationDisableFeaturesRequest, PoolMirroring) {
+TEST_F(TestMockOperationDisableFeaturesRequest, Mirroring) {
   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
 
   MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_POOL);
@@ -479,46 +478,6 @@ TEST_F(TestMockOperationDisableFeaturesRequest, PoolMirroring) {
   ASSERT_EQ(0, cond_ctx.wait());
 }
 
-TEST_F(TestMockOperationDisableFeaturesRequest, ImageMirroring) {
-  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
-
-  MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_IMAGE);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false));
-
-  MockOperationImageCtx mock_image_ctx(*ictx);
-  MockExclusiveLock mock_exclusive_lock;
-  MockJournal mock_journal;
-  MockObjectMap mock_object_map;
-  initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
-                     mock_object_map);
-
-  expect_verify_lock_ownership(mock_image_ctx);
-
-  MockRemoveJournalRequest mock_remove_journal_request;
-  MockDisableMirrorRequest mock_disable_mirror_request;
-
-  ::testing::InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_block_writes(mock_image_ctx);
-  expect_is_journal_replaying(*mock_image_ctx.journal);
-  expect_block_requests(mock_image_ctx);
-  expect_unblock_requests(mock_image_ctx);
-  expect_unblock_writes(mock_image_ctx);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond cond_ctx;
-  MockDisableFeaturesRequest *req = new MockDisableFeaturesRequest(
-    mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING, false);
-  {
-    std::shared_lock owner_locker{mock_image_ctx.owner_lock};
-    req->send();
-  }
-  ASSERT_EQ(-EINVAL, cond_ctx.wait());
-}
-
 TEST_F(TestMockOperationDisableFeaturesRequest, MirroringError) {
   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
 
index f4c4fc5d442556bac6c6c0be73af34ba743b25c2..70f6aa5320979d9e3570754afd8c4f9a4b04476a 100644 (file)
@@ -6,11 +6,9 @@
 #include "test/librbd/mock/MockImageCtx.h"
 #include "cls/rbd/cls_rbd_client.h"
 #include "librbd/Operations.h"
-#include "librbd/api/Mirror.h"
 #include "librbd/internal.h"
 #include "librbd/image/SetFlagsRequest.h"
 #include "librbd/io/AioCompletion.h"
-#include "librbd/mirror/DisableRequest.h"
 #include "librbd/mirror/EnableRequest.h"
 #include "librbd/journal/CreateRequest.h"
 #include "librbd/journal/Types.h"
@@ -96,7 +94,9 @@ public:
   static EnableRequest *s_instance;
   Context *on_finish = nullptr;
 
-  static EnableRequest *create(MockOperationImageCtx *image_ctx, Context *on_finish) {
+  static EnableRequest *create(MockOperationImageCtx *image_ctx,
+                               mirror_image_mode_t mirror_image_mode,
+                               Context *on_finish) {
     ceph_assert(s_instance != nullptr);
     s_instance->on_finish = on_finish;
     return s_instance;
@@ -485,7 +485,7 @@ TEST_F(TestMockOperationEnableFeaturesRequest, SetFlagsError) {
   ASSERT_EQ(-EINVAL, cond_ctx.wait());
 }
 
-TEST_F(TestMockOperationEnableFeaturesRequest, PoolMirroring) {
+TEST_F(TestMockOperationEnableFeaturesRequest, Mirroring) {
   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
 
   MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_POOL);
@@ -533,48 +533,6 @@ TEST_F(TestMockOperationEnableFeaturesRequest, PoolMirroring) {
   ASSERT_EQ(0, cond_ctx.wait());
 }
 
-TEST_F(TestMockOperationEnableFeaturesRequest, ImageMirroring) {
-  REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-  ensure_features_disabled(ictx, RBD_FEATURE_JOURNALING);
-
-  MirrorModeEnabler mirror_mode_enabler(m_ioctx, cls::rbd::MIRROR_MODE_IMAGE);
-
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false)); // snapshot mode
-
-  uint64_t features;
-  ASSERT_EQ(0, librbd::get_features(ictx, &features));
-
-  MockOperationImageCtx mock_image_ctx(*ictx);
-  MockExclusiveLock mock_exclusive_lock;
-  MockJournal mock_journal;
-  MockObjectMap mock_object_map;
-  initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal,
-                      mock_object_map);
-
-  expect_verify_lock_ownership(mock_image_ctx);
-
-  MockCreateJournalRequest mock_create_journal_request;
-  MockEnableMirrorRequest mock_enable_mirror_request;
-
-  ::testing::InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_block_writes(mock_image_ctx);
-  expect_unblock_writes(mock_image_ctx);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond cond_ctx;
-  MockEnableFeaturesRequest *req = new MockEnableFeaturesRequest(
-    mock_image_ctx, &cond_ctx, 0, RBD_FEATURE_JOURNALING);
-  {
-    std::shared_lock owner_locker{mock_image_ctx.owner_lock};
-    req->send();
-  }
-  ASSERT_EQ(-EINVAL, cond_ctx.wait());
-}
-
 TEST_F(TestMockOperationEnableFeaturesRequest, JournalingError) {
   REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
 
@@ -598,6 +556,7 @@ TEST_F(TestMockOperationEnableFeaturesRequest, JournalingError) {
   expect_verify_lock_ownership(mock_image_ctx);
 
   MockCreateJournalRequest mock_create_journal_request;
+  MockEnableMirrorRequest mock_enable_mirror_request;
 
   ::testing::InSequence seq;
   expect_prepare_lock(mock_image_ctx);
index 6b42880ede347c6aec9a79922e3be1454e5a29e2..19512036ad365f70b0b780f9bd4efce6680bfdf5 100644 (file)
@@ -636,7 +636,8 @@ TEST_F(TestMigration, MirroringSamePool)
 
   ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
 
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+              m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
   librbd::mirror_image_info_t info;
   ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
   ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
@@ -653,7 +654,8 @@ TEST_F(TestMigration, MirroringAbort)
 
   ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
 
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+              m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
   librbd::mirror_image_info_t info;
   ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
   ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
@@ -675,7 +677,8 @@ TEST_F(TestMigration, MirroringOtherPoolDisabled)
 
   ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
 
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+              m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
   librbd::mirror_image_info_t info;
   ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
   ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
@@ -694,7 +697,8 @@ TEST_F(TestMigration, MirroringOtherPoolEnabled)
   ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(_other_pool_ioctx,
                                                RBD_MIRROR_MODE_IMAGE));
 
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(m_ictx, false));
+  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+              m_ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
   librbd::mirror_image_info_t info;
   ASSERT_EQ(0, librbd::api::Mirror<>::image_get_info(m_ictx, &info));
   ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED, info.state);
index 17f9cef43fb8c21ebd2b48f2ba8f2a3f635a9c4e..4f9cbdba234ab8a198c10cc05952fb90981fd016 100644 (file)
@@ -110,7 +110,7 @@ public:
 
     ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, mirror_mode));
 
-    ASSERT_EQ(expected_r, image.mirror_image_enable());
+    ASSERT_EQ(expected_r, image.mirror_image_enable2(mirror_image_mode));
 
     librbd::mirror_image_info_t mirror_image;
     ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image, sizeof(mirror_image)));
@@ -248,7 +248,7 @@ public:
     ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
 
     if (enable_mirroring) {
-      ASSERT_EQ(0, image.mirror_image_enable());
+      ASSERT_EQ(0, image.mirror_image_enable2(mirror_image_mode));
     }
 
     ASSERT_EQ(expected_r, image.update_features(features, enable));
@@ -332,7 +332,7 @@ public:
     ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
 
     if (enable_mirroring) {
-      ASSERT_EQ(0, image.mirror_image_enable());
+      ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
     }
 
     if (demote) {
@@ -358,7 +358,7 @@ public:
     ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
 
     if (enable_mirroring) {
-      ASSERT_EQ(0, image.mirror_image_enable());
+      ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
     }
 
     std::string image_id;
@@ -487,7 +487,7 @@ TEST_F(TestMirroring, DisableImageMirrorWithPeer) {
 
   librbd::Image image;
   ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
-  ASSERT_EQ(0, image.mirror_image_enable());
+  ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL));
 
   setup_mirror_peer(m_ioctx, image);
 
@@ -641,13 +641,13 @@ TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage) {
                       RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_DISABLED);
 }
 
-TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage_MirroringEnabled) {
+TEST_F(TestMirroring, EnableJournaling_In_MirrorModeImage_SnapshotMirroringEnabled) {
   uint64_t init_features = 0;
   init_features |= RBD_FEATURE_OBJECT_MAP;
   init_features |= RBD_FEATURE_EXCLUSIVE_LOCK;
   uint64_t features = RBD_FEATURE_JOURNALING;
   check_mirroring_on_update_features(init_features, true, true, features,
-                      -EINVAL, RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_ENABLED,
+                      0, RBD_MIRROR_MODE_IMAGE, RBD_MIRROR_IMAGE_ENABLED,
                       RBD_MIRROR_IMAGE_MODE_SNAPSHOT);
 }
 
@@ -889,7 +889,8 @@ TEST_F(TestMirroring, AioPromoteDemote) {
 
     images.emplace_back();
     ASSERT_EQ(0, m_rbd.open(m_ioctx, images.back(), image_name.c_str()));
-    ASSERT_EQ(0, images.back().mirror_image_enable());
+    ASSERT_EQ(0, images.back().mirror_image_enable2(
+                RBD_MIRROR_IMAGE_MODE_JOURNAL));
   }
 
   // demote all images
@@ -1108,7 +1109,6 @@ TEST_F(TestMirroring, Snapshot)
 
   uint64_t features;
   ASSERT_TRUE(get_features(&features));
-  features &= ~RBD_FEATURE_JOURNALING;
   int order = 20;
   ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
                              &order));
@@ -1124,7 +1124,7 @@ TEST_F(TestMirroring, Snapshot)
   ASSERT_EQ(-EINVAL, image.mirror_image_create_snapshot(&snap_id));
   ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_IMAGE));
   ASSERT_EQ(-EINVAL, image.mirror_image_create_snapshot(&snap_id));
-  ASSERT_EQ(0, image.mirror_image_enable());
+  ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
   librbd::mirror_image_mode_t mode;
   ASSERT_EQ(0, image.mirror_image_get_mode(&mode));
   ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode);
@@ -1186,13 +1186,12 @@ TEST_F(TestMirroring, SnapshotRemoveOnDisable)
 
   uint64_t features;
   ASSERT_TRUE(get_features(&features));
-  features &= ~RBD_FEATURE_JOURNALING;
   int order = 20;
   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()));
-  ASSERT_EQ(0, image.mirror_image_enable());
+  ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
   uint64_t snap_id;
   ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
 
@@ -1238,7 +1237,7 @@ TEST_F(TestMirroring, SnapshotUnlinkPeer)
                              &order));
   librbd::Image image;
   ASSERT_EQ(0, m_rbd.open(m_ioctx, image, image_name.c_str()));
-  ASSERT_EQ(0, image.mirror_image_enable());
+  ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
   uint64_t snap_id;
   ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
   librbd::snap_mirror_primary_namespace_t mirror_snap;
@@ -1299,7 +1298,6 @@ TEST_F(TestMirroring, SnapshotImageState)
 
   uint64_t features;
   ASSERT_TRUE(get_features(&features));
-  features &= ~RBD_FEATURE_JOURNALING;
   int order = 20;
   ASSERT_EQ(0, m_rbd.create2(m_ioctx, image_name.c_str(), 4096, features,
                              &order));
@@ -1409,14 +1407,13 @@ TEST_F(TestMirroring, SnapshotPromoteDemote)
 
   uint64_t features;
   ASSERT_TRUE(get_features(&features));
-  features &= ~RBD_FEATURE_JOURNALING;
   int order = 20;
   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()));
-  ASSERT_EQ(0, image.mirror_image_enable());
+  ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT));
   librbd::mirror_image_mode_t mode;
   ASSERT_EQ(0, image.mirror_image_get_mode(&mode));
   ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode);
index 3077a806b8b58f7aaaca9939cfd1c8b7050e0dd0..b82d6b3a45ea648fa8838096ef5f4a7a9f5cb795 100644 (file)
@@ -2052,15 +2052,13 @@ class TestMirroring(object):
             self.rbd.remove(ioctx, image_name + str(i))
 
     def test_mirror_image_create_snapshot(self):
-        if self.image.features() & RBD_FEATURE_JOURNALING != 0:
-            self.image.update_features(RBD_FEATURE_JOURNALING, False)
-
         assert_raises(InvalidArgument, self.image.mirror_image_create_snapshot)
 
         peer1_uuid = self.rbd.mirror_peer_add(ioctx, "cluster1", "client")
         peer2_uuid = self.rbd.mirror_peer_add(ioctx, "cluster2", "client")
         self.rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)
-        self.image.mirror_image_enable()
+        self.image.mirror_image_disable(False)
+        self.image.mirror_image_enable(RBD_MIRROR_IMAGE_MODE_SNAPSHOT)
         mode = self.image.mirror_image_get_mode()
         eq(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mode)
 
index c56fffc1d18c55be1b427233c47ac5309b04b3e4..bd7d824cc70543435d81a15408cc784416fdddf8 100644 (file)
@@ -464,7 +464,8 @@ TEST_F(TestImageReplayer, BootstrapMirrorDisabling)
                                                RBD_MIRROR_MODE_IMAGE));
   librbd::ImageCtx *ictx;
   open_remote_image(&ictx);
-  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(ictx, false));
+  ASSERT_EQ(0, librbd::api::Mirror<>::image_enable(
+              ictx, RBD_MIRROR_IMAGE_MODE_JOURNAL, false));
   cls::rbd::MirrorImage mirror_image;
   ASSERT_EQ(0, librbd::cls_client::mirror_image_get(&m_remote_ioctx, ictx->id,
                                                     &mirror_image));
index 8433ab88afd2966973d495721dd1a95159b9f874..78cab0516adf90e20d8e1150ebf95311c81de581 100644 (file)
@@ -142,7 +142,7 @@ public:
       librbd::Image image;
       librbd::RBD rbd;
       rbd.open(ioctx, image, name.c_str());
-      image.mirror_image_enable();
+      image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
 
       librbd::mirror_image_info_t mirror_image_info;
       ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,
@@ -189,7 +189,7 @@ public:
       librbd::Image image;
       librbd::RBD rbd;
       rbd.open(cioctx, image, name.c_str());
-      image.mirror_image_enable();
+      image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL);
 
       librbd::mirror_image_info_t mirror_image_info;
       ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,