]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: support creating images with non-primary journals
authorJason Dillaman <dillaman@redhat.com>
Thu, 24 Mar 2016 02:28:55 +0000 (22:28 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 29 Mar 2016 19:19:25 +0000 (15:19 -0400)
When rbd-mirror initially creates a replicated image in the
local pool, the journal should be flagged as non-primary to
(1) prevent local ops againsts the image and (2) provide a
clean chain of replicated tags.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/Journal.cc
src/librbd/Journal.h
src/librbd/internal.cc
src/librbd/internal.h
src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc

index ad8900d1d06e5a5aaa5aacba80cfd5cc7fa44c48..0e905776bce279e801a2199bf3cdfb281d04a250 100644 (file)
@@ -313,7 +313,7 @@ bool Journal<I>::is_journal_supported(I &image_ctx) {
 template <typename I>
 int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
                       uint8_t order, uint8_t splay_width,
-                      const std::string &object_pool) {
+                      const std::string &object_pool, bool non_primary) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
 
@@ -341,12 +341,16 @@ int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
   }
 
   // create tag class for this image's journal events
-  bufferlist tag_data;
-  ::encode(journal::TagData(), tag_data);
+  journal::TagData tag_data;
+  tag_data.mirror_uuid = (!non_primary ? LOCAL_MIRROR_UUID :
+                                         ORPHAN_MIRROR_UUID);
+
+  bufferlist tag_data_bl;
+  ::encode(tag_data, tag_data_bl);
 
   C_SaferCond tag_ctx;
   cls::journal::Tag tag;
-  journaler.allocate_tag(cls::journal::Tag::TAG_CLASS_NEW, tag_data,
+  journaler.allocate_tag(cls::journal::Tag::TAG_CLASS_NEW, tag_data_bl,
                          &tag, &tag_ctx);
   r = tag_ctx.wait();
   if (r < 0) {
index ca294fe27d17ca4066cdde0d6d36f480c054d5b0..5258ae7db3fa390cb0f242bc3ebf2eef4c2f3c55 100644 (file)
@@ -95,7 +95,7 @@ public:
   static bool is_journal_supported(ImageCtxT &image_ctx);
   static int create(librados::IoCtx &io_ctx, const std::string &image_id,
                    uint8_t order, uint8_t splay_width,
-                   const std::string &object_pool);
+                   const std::string &object_pool, bool non_primary);
   static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
   static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
 
index 3b3388182d0b20f33b1f724f13848bcebe08d900..270076d59221d8cdf5b6340c54785592b48acf2d 100644 (file)
@@ -200,6 +200,46 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
   return 0;
 }
 
+int mirror_image_enable(CephContext *cct, librados::IoCtx &io_ctx,
+                        const std::string &id,
+                        const std::string &global_image_id) {
+  cls::rbd::MirrorImage mirror_image_internal;
+  int r = cls_client::mirror_image_get(&io_ctx, id, &mirror_image_internal);
+  if (r < 0 && r != -ENOENT) {
+    lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  if (mirror_image_internal.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+    // mirroring is already enabled
+    return 0;
+  } else if (r != -ENOENT) {
+    lderr(cct) << "cannot enable mirroring: currently disabling" << dendl;
+    return -EINVAL;
+  }
+
+  mirror_image_internal.state =
+    cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
+  if (global_image_id.empty()) {
+    uuid_d uuid_gen;
+    uuid_gen.generate_random();
+    mirror_image_internal.global_image_id = uuid_gen.to_string();
+  } else {
+    mirror_image_internal.global_image_id = global_image_id;
+  }
+
+  r = cls_client::mirror_image_set(&io_ctx, id, mirror_image_internal);
+  if (r < 0) {
+    lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  ldout(cct, 20) << "image mirroring is enabled: global_id=" <<
+    mirror_image_internal.global_image_id << dendl;
+
+  return 0;
+}
+
 int mirror_image_enable_internal(ImageCtx *ictx) {
   CephContext *cct = ictx->cct;
 
@@ -224,42 +264,11 @@ int mirror_image_enable_internal(ImageCtx *ictx) {
     return -EINVAL;
   }
 
-  cls::rbd::MirrorImage mirror_image_internal;
-  r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
-      &mirror_image_internal);
-  if (r < 0 && r != -ENOENT) {
-    lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-
-  if (mirror_image_internal.state ==
-      cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED) {
-    // mirroring is already enabled
-    return 0;
-  }
-  else if (r != -ENOENT) {
-    lderr(cct) << "cannot enable mirroring: mirroring image is in "
-      "disabling state" << dendl;
-    return -EINVAL;
-  }
-
-  mirror_image_internal.state =
-    cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
-
-  uuid_d uuid_gen;
-  uuid_gen.generate_random();
-  mirror_image_internal.global_image_id = uuid_gen.to_string();
-
-  r = cls_client::mirror_image_set(&ictx->md_ctx, ictx->id,
-      mirror_image_internal);
+  r = mirror_image_enable(cct, ictx->md_ctx, ictx->id, "");
   if (r < 0) {
-    lderr(cct) << "cannot enable mirroring: " << cpp_strerror(r) << dendl;
     return r;
   }
 
-  ldout(cct, 20) << "image mirroring is enabled: global_id=" <<
-    mirror_image_internal.global_image_id << dendl;
-
   return 0;
 }
 
@@ -969,8 +978,8 @@ remove_mirroring_image:
   int create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size,
                int order, uint64_t features, uint64_t stripe_unit,
                uint64_t stripe_count, uint8_t journal_order,
-               uint8_t journal_splay_width,
-               const std::string &journal_pool)
+                uint8_t journal_splay_width, const std::string &journal_pool,
+                const std::string &non_primary_global_image_id)
   {
     ostringstream bid_ss;
     uint32_t extra;
@@ -980,6 +989,7 @@ remove_mirroring_image:
     CephContext *cct = (CephContext *)io_ctx.cct();
 
     file_layout_t layout;
+    bool force_non_primary = !non_primary_global_image_id.empty();
 
     int r = validate_pool(io_ctx, cct);
     if (r < 0) {
@@ -1069,44 +1079,46 @@ remove_mirroring_image:
         goto err_remove_object_map;
       }
 
-      r = Journal<>::create(io_ctx, id, journal_order, journal_splay_width,
-                           journal_pool);
+      rbd_mirror_mode_t mirror_mode;
+      r = librbd::mirror_mode_get(io_ctx, &mirror_mode);
       if (r < 0) {
-        lderr(cct) << "error creating journal: " << cpp_strerror(r) << dendl;
+        lderr(cct) << "error in retrieving pool mirroring status: "
+                   << cpp_strerror(r) << dendl;
         goto err_remove_object_map;
       }
 
-      rbd_mirror_mode_t mirror_mode;
-      r = librbd::mirror_mode_get(io_ctx, &mirror_mode);
+      r = Journal<>::create(io_ctx, id, journal_order, journal_splay_width,
+                           journal_pool, force_non_primary);
       if (r < 0) {
-        lderr(cct) << "error in retrieving pool mirroring status: "
-          << cpp_strerror(r) << dendl;
+        lderr(cct) << "error creating journal: " << cpp_strerror(r) << dendl;
         goto err_remove_object_map;
       }
 
-      if (mirror_mode == RBD_MIRROR_MODE_POOL) {
-        ImageCtx *img_ctx = new ImageCtx("", id, nullptr, io_ctx, false);
-        r = img_ctx->state->open();
-        if (r < 0) {
-          lderr(cct) << "error opening image: " << cpp_strerror(r) << dendl;
-          delete img_ctx;
-          goto err_remove_object_map;
-        }
-        r = mirror_image_enable_internal(img_ctx);
+      if (mirror_mode == RBD_MIRROR_MODE_POOL || force_non_primary) {
+        r = mirror_image_enable(cct, io_ctx, id, non_primary_global_image_id);
         if (r < 0) {
           lderr(cct) << "error enabling mirroring: " << cpp_strerror(r)
-            << dendl;
-          img_ctx->state->close();
-          goto err_remove_object_map;
+                     << dendl;
+          goto err_remove_journal;
         }
-        img_ctx->state->close();
       }
-
+    } else if (force_non_primary) {
+      // journaling should have been enabled
+      assert(false);
     }
 
     ldout(cct, 2) << "done." << dendl;
     return 0;
 
+  err_remove_journal:
+    if ((features & RBD_FEATURE_JOURNALING) != 0) {
+      remove_r = Journal<>::remove(io_ctx, id);
+      if (remove_r < 0) {
+        lderr(cct) << "error cleaning up journal after creation failed: "
+                   << cpp_strerror(remove_r) << dendl;
+      }
+    }
+
   err_remove_object_map:
     if ((features & RBD_FEATURE_OBJECT_MAP) != 0) {
       remove_r = ObjectMap::remove(io_ctx, id);
@@ -1274,7 +1286,8 @@ remove_mirroring_image:
       opts.get(RBD_IMAGE_OPTION_JOURNAL_POOL, &journal_pool);
 
       r = create_v2(io_ctx, imgname, bid, size, order, features, stripe_unit,
-                   stripe_count, journal_order, journal_splay_width, journal_pool);
+                   stripe_count, journal_order, journal_splay_width,
+                    journal_pool, "");
     }
 
     int r1 = opts.set(RBD_IMAGE_OPTION_ORDER, order);
@@ -1617,7 +1630,7 @@ remove_mirroring_image:
 
           r = Journal<>::create(ictx->md_ctx, ictx->id, ictx->journal_order,
                                ictx->journal_splay_width,
-                               ictx->journal_pool);
+                               ictx->journal_pool, false);
           if (r < 0) {
             lderr(cct) << "error creating image journal: " << cpp_strerror(r)
                        << dendl;
index b92e57274b80a9c3dbc315a04fdbed13852ab25b..ae7b1732b082c4d26289aa6c9596f14e050f8f63 100644 (file)
@@ -96,6 +96,12 @@ namespace librbd {
             uint64_t stripe_unit, uint64_t stripe_count);
   int create(IoCtx& io_ctx, const char *imgname, uint64_t size,
             ImageOptions& opts);
+  int create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size,
+               int order, uint64_t features, uint64_t stripe_unit,
+               uint64_t stripe_count, uint8_t journal_order,
+               uint8_t journal_splay_width,
+               const std::string &journal_pool,
+                const std::string &non_primary_global_image_id);
   int clone(IoCtx& p_ioctx, const char *p_name, const char *p_snap_name,
            IoCtx& c_ioctx, const char *c_name,
            uint64_t features, int *c_order,
index cd0646b0abc6a1e55721d9120d42af0be6cb9f8a..5b112222c1f9fdeba91924e47d11a351454738b2 100644 (file)
@@ -49,11 +49,20 @@ struct C_CreateImage : public Context {
     // TODO: rbd-mirror should offer a feature mask capability
     RWLock::RLocker snap_locker(remote_image_ctx->snap_lock);
     int order = remote_image_ctx->order;
-    r = librbd::create(local_io_ctx, local_image_name.c_str(),
-                       remote_image_ctx->size, false,
-                       remote_image_ctx->features, &order,
-                       remote_image_ctx->stripe_unit,
-                       remote_image_ctx->stripe_count);
+
+    CephContext *cct = reinterpret_cast<CephContext*>(local_io_ctx.cct());
+    uint64_t journal_order = cct->_conf->rbd_journal_order;
+    uint64_t journal_splay_width = cct->_conf->rbd_journal_splay_width;
+    std::string journal_pool = cct->_conf->rbd_journal_pool;
+
+    r = librbd::create_v2(local_io_ctx, local_image_name.c_str(),
+                          reinterpret_cast<uint64_t>(this),
+                          remote_image_ctx->size, order,
+                          remote_image_ctx->features,
+                          remote_image_ctx->stripe_unit,
+                          remote_image_ctx->stripe_count,
+                          journal_order, journal_splay_width, journal_pool,
+                          "global-image-id");
     on_finish->complete(r);
   }
 };