]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: permit mirroring to be enabled upon image creation
authorJason Dillaman <dillaman@redhat.com>
Mon, 20 Apr 2020 21:04:02 +0000 (17:04 -0400)
committerNathan Cutler <ncutler@suse.com>
Wed, 29 Apr 2020 12:06:58 +0000 (14:06 +0200)
The librbd create API's ImageOptions parameter now supports passing
the mirror image mode.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 37f6fa8fe95729af845100e28df8b8e0668c2270)

src/include/rbd/librbd.h
src/librbd/image/CreateRequest.cc
src/librbd/image/CreateRequest.h
src/librbd/internal.cc
src/librbd/mirror/EnableRequest.cc
src/test/librbd/test_librbd.cc

index 25068dbf4e59c659083d83708ebda0000977ef1c..d85cd36504b66def6c2599dbf1eae7f450f9ab6e 100644 (file)
@@ -292,6 +292,7 @@ enum {
   RBD_IMAGE_OPTION_DATA_POOL = 10,
   RBD_IMAGE_OPTION_FLATTEN = 11,
   RBD_IMAGE_OPTION_CLONE_FORMAT = 12,
+  RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE = 13,
 };
 
 typedef enum {
index dbc03e7a221aa55b7a1a0378126783aa7df1d5c6..ffa3dbc68a8bbdf2071d6490db198297c02edba6 100644 (file)
@@ -133,7 +133,10 @@ CreateRequest<I>::CreateRequest(const ConfigProxy& config, IoCtx &ioctx,
   m_id_obj = util::id_obj_name(m_image_name);
   m_header_obj = util::header_name(m_image_id);
   m_objmap_name = ObjectMap<>::object_map_name(m_image_id, CEPH_NOSNAP);
-  m_force_non_primary = !non_primary_global_image_id.empty();
+  if (!non_primary_global_image_id.empty() &&
+      (m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK) == 0) {
+    m_create_flags |= CREATE_FLAG_FORCE_MIRROR_ENABLE;
+  }
 
   if (image_options.get(RBD_IMAGE_OPTION_FEATURES, &m_features) != 0) {
     m_features = librbd::rbd_features_from_string(
@@ -603,7 +606,7 @@ void CreateRequest<I>::journal_create() {
   // only link to remote primary mirror uuid if in journal-based
   // mirroring mode
   bool use_primary_mirror_uuid = (
-    m_force_non_primary &&
+    !m_non_primary_global_image_id.empty() &&
     m_mirror_image_mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL);
 
   librbd::journal::TagData tag_data;
@@ -635,9 +638,11 @@ void CreateRequest<I>::handle_journal_create(int r) {
 
 template<typename I>
 void CreateRequest<I>::mirror_image_enable() {
-  if (((m_mirror_mode != cls::rbd::MIRROR_MODE_POOL) && !m_force_non_primary) ||
-      ((m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK) ==
-          CREATE_FLAG_SKIP_MIRROR_ENABLE)) {
+  auto mirror_enable_flag = (m_create_flags & CREATE_FLAG_MIRROR_ENABLE_MASK);
+
+  if ((m_mirror_mode != cls::rbd::MIRROR_MODE_POOL &&
+       mirror_enable_flag != CREATE_FLAG_FORCE_MIRROR_ENABLE) ||
+      (mirror_enable_flag == CREATE_FLAG_SKIP_MIRROR_ENABLE)) {
     complete(0);
     return;
   }
index 632ba077ac964a07a160c35c74b29f8d2e81de2c..ce924e34ae31c5de22d337d2d24f5b43feae5cbf 100644 (file)
@@ -123,7 +123,6 @@ private:
 
   CephContext *m_cct;
   int m_r_saved = 0;  // used to return actual error after cleanup
-  bool m_force_non_primary;
   file_layout_t m_layout;
   std::string m_id_obj, m_header_obj, m_objmap_name;
 
index 3dbbcd00918d835988c51d4a7bf0eee012c8635e..f4350c8ad27d9085abfcad926fe6ee2971cd4256 100644 (file)
@@ -311,6 +311,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
     {RBD_IMAGE_OPTION_DATA_POOL, STR},
     {RBD_IMAGE_OPTION_FLATTEN, UINT64},
     {RBD_IMAGE_OPTION_CLONE_FORMAT, UINT64},
+    {RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE, UINT64},
   };
 
   std::string image_option_name(int optname) {
@@ -341,6 +342,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
       return "flatten";
     case RBD_IMAGE_OPTION_CLONE_FORMAT:
       return "clone_format";
+    case RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE:
+      return "mirror_image_mode";
     default:
       return "unknown (" + stringify(optname) + ")";
     }
@@ -689,15 +692,19 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
       api::Config<>::apply_pool_overrides(io_ctx, &config);
 
       uint32_t create_flags = 0U;
+      uint64_t mirror_image_mode = RBD_MIRROR_IMAGE_MODE_JOURNAL;
       if (skip_mirror_enable) {
         create_flags = image::CREATE_FLAG_SKIP_MIRROR_ENABLE;
+      } else if (opts.get(RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE,
+                          &mirror_image_mode) == 0) {
+        create_flags = image::CREATE_FLAG_FORCE_MIRROR_ENABLE;
       }
 
       C_SaferCond cond;
       image::CreateRequest<> *req = image::CreateRequest<>::create(
         config, io_ctx, image_name, id, size, opts, create_flags,
-        cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, non_primary_global_image_id,
-        primary_mirror_uuid, op_work_queue, &cond);
+        static_cast<cls::rbd::MirrorImageMode>(mirror_image_mode),
+        non_primary_global_image_id, primary_mirror_uuid, op_work_queue, &cond);
       req->send();
 
       r = cond.wait();
index cb61631f4860056546082b4847128a719e02bba1..b99f9d71b306d4a90c4087e56667355ce992e079 100644 (file)
@@ -160,7 +160,8 @@ void EnableRequest<I>::open_image() {
 
   auto ctx = create_context_callback<
     EnableRequest<I>, &EnableRequest<I>::handle_open_image>(this);
-  m_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT, ctx);
+  m_image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT |
+                           OPEN_FLAG_IGNORE_MIGRATING, ctx);
 }
 
 template <typename I>
index 86aa95c88b63bd154f08f15366f024a1a9423c24..d091fd7ca5a04b8ba9044e8b8f36f673c72e30a4 100644 (file)
@@ -6592,6 +6592,34 @@ TEST_F(TestLibRBD, MirrorPeerAttributes) {
   ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED));
 }
 
+TEST_F(TestLibRBD, CreateWithMirrorEnabled) {
+  REQUIRE_FORMAT_V2();
+
+  librados::IoCtx ioctx;
+  ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx));
+
+  librbd::RBD rbd;
+  ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE));
+
+  librbd::ImageOptions image_options;
+  ASSERT_EQ(0, image_options.set(
+                 RBD_IMAGE_OPTION_MIRROR_IMAGE_MODE,
+                 static_cast<uint64_t>(RBD_MIRROR_IMAGE_MODE_SNAPSHOT)));
+
+  std::string image_name = get_temp_image_name();
+  ASSERT_EQ(0, rbd.create4(ioctx, image_name.c_str(), 2<<20, image_options));
+
+  librbd::Image image;
+  ASSERT_EQ(0, rbd.open(ioctx, image, image_name.c_str(), NULL));
+
+  librbd::mirror_image_mode_t mirror_image_mode;
+  ASSERT_EQ(0, image.mirror_image_get_mode(&mirror_image_mode));
+  ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT, mirror_image_mode);
+
+  ASSERT_EQ(0, image.mirror_image_disable(true));
+  ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED));
+}
+
 TEST_F(TestLibRBD, FlushCacheWithCopyupOnExternalSnapshot) {
   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);