]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: rbd-mirroring: Enable image mirroring when pool-level mirroring is enabled
authorRicardo Dias <rdias@suse.com>
Tue, 22 Mar 2016 11:43:51 +0000 (11:43 +0000)
committerRicardo Dias <rdias@suse.com>
Tue, 29 Mar 2016 08:45:48 +0000 (09:45 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/librbd/internal.cc

index 73ebb0a24c1c6c095cdd2ed4688a61bb4bae59fb..8de3d53bbced3882f95701b55437dbe4bd5ab177 100644 (file)
@@ -580,6 +580,38 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
     return (*opts_)->empty();
   }
 
+  int list_images_v2(IoCtx& io_ctx, map<string, string> &images) {
+    CephContext *cct = (CephContext *)io_ctx.cct();
+    ldout(cct, 20) << "list_images_v2 " << &io_ctx << dendl;
+
+    // new format images are accessed by class methods
+    int r;
+    int max_read = 1024;
+    string last_read = "";
+    do {
+      map<string, string> images_page;
+      r = cls_client::dir_list(&io_ctx, RBD_DIRECTORY,
+                          last_read, max_read, &images_page);
+      if (r < 0 && r != -ENOENT) {
+        lderr(cct) << "error listing image in directory: "
+                   << cpp_strerror(r) << dendl;
+        return r;
+      } else if (r == -ENOENT) {
+        break;
+      }
+      for (map<string, string>::const_iterator it = images_page.begin();
+          it != images_page.end(); ++it) {
+       images.insert(*it);
+      }
+      if (!images_page.empty()) {
+       last_read = images_page.rbegin()->first;
+      }
+      r = images_page.size();
+    } while (r == max_read);
+
+    return 0;
+  }
+
   int list(IoCtx& io_ctx, vector<string>& names)
   {
     CephContext *cct = (CephContext *)io_ctx.cct();
@@ -602,27 +634,15 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
       }
     }
 
-    // new format images are accessed by class methods
-    int max_read = 1024;
-    string last_read = "";
-    do {
-      map<string, string> images;
-      r = cls_client::dir_list(&io_ctx, RBD_DIRECTORY,
-                          last_read, max_read, &images);
-      if (r < 0) {
-        lderr(cct) << "error listing image in directory: " 
-                   << cpp_strerror(r) << dendl;   
-        return r;
-      }
-      for (map<string, string>::const_iterator it = images.begin();
-          it != images.end(); ++it) {
-       names.push_back(it->first);
-      }
-      if (!images.empty()) {
-       last_read = images.rbegin()->first;
-      }
-      r = images.size();
-    } while (r == max_read);
+    map<string, string> images;
+    r = list_images_v2(io_ctx, images);
+    if (r < 0) {
+      lderr(cct) << "error listing v2 images: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+    for (const auto& img_pair : images) {
+      names.push_back(img_pair.first);
+    }
 
     return 0;
   }
@@ -2797,11 +2817,113 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
       }
     }
 
+    if (current_mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) {
+      r = cls_client::mirror_mode_set(&io_ctx, cls::rbd::MIRROR_MODE_IMAGE);
+      if (r < 0) {
+        lderr(cct) << "Failed to set mirror mode to image: "
+          << cpp_strerror(r) << dendl;
+        return r;
+      }
+    }
+
+    if (next_mirror_mode == cls::rbd::MIRROR_MODE_IMAGE) {
+      return 0;
+    }
+
+    struct rollback_state_t {
+      IoCtx *io_ctx;
+      bool do_rollback;
+      cls::rbd::MirrorMode mirror_mode;
+      bool enable;
+      std::vector<std::pair<ImageCtx *, bool> > img_ctxs;
+
+      rollback_state_t(IoCtx *io_ctx, cls::rbd::MirrorMode mirror_mode, bool enable) :
+        io_ctx(io_ctx),
+        do_rollback(true),
+        mirror_mode(mirror_mode),
+        enable(enable) {
+      }
+      ~rollback_state_t() {
+        CephContext *cct = reinterpret_cast<CephContext *>(io_ctx->cct());
+        if (do_rollback && mirror_mode != cls::rbd::MIRROR_MODE_IMAGE) {
+          int r = cls_client::mirror_mode_set(io_ctx, mirror_mode);
+          if (r < 0) {
+            lderr(cct) << "Failed to rollback mirror mode: " << cpp_strerror(r)
+              << dendl;
+          }
+        }
+        for (const auto& pair : img_ctxs) {
+          if (do_rollback && pair.second) {
+            int r = enable ? mirror_image_disable(pair.first, false) :
+              mirror_image_enable(pair.first);
+            if (r < 0) {
+              lderr(cct) << "Failed to rollback mirroring state for image id "
+                << pair.first->id << ": " << cpp_strerror(r) << dendl;
+            }
+          }
+
+          int r = pair.first->state->close();
+          if (r < 0) {
+            lderr(cct) << "error closing image " << pair.first->id << ": "
+              << cpp_strerror(r) << dendl;
+          }
+        }
+      }
+    } rb_state(&io_ctx, current_mirror_mode,
+                     next_mirror_mode == cls::rbd::MIRROR_MODE_POOL);
+
+
+    if (next_mirror_mode == cls::rbd::MIRROR_MODE_POOL) {
+
+      map<string, string> images;
+      r = list_images_v2(io_ctx, images);
+      if (r < 0) {
+        lderr(cct) << "Failed listing images: " << cpp_strerror(r) << dendl;
+        return r;
+      }
+
+      for (const auto& img_pair : images) {
+        uint64_t features;
+        r = cls_client::get_features(&io_ctx, util::header_name(img_pair.second),
+                                     CEPH_NOSNAP, &features);
+        if (r < 0) {
+          lderr(cct) << "error getting features for image " << img_pair.first
+            << ": " << cpp_strerror(r) << dendl;
+          return r;
+        }
+
+        if ((features & RBD_FEATURE_JOURNALING) != 0) {
+          ImageCtx *img_ctx = new ImageCtx("", img_pair.second, nullptr,
+                                           io_ctx, false);
+          r = img_ctx->state->open();
+          if (r < 0) {
+            lderr(cct) << "error opening image "<< img_pair.first << ": "
+              << cpp_strerror(r) << dendl;
+            delete img_ctx;
+            return r;
+          }
+
+          r = mirror_image_enable(img_ctx);
+          if (r < 0) {
+            lderr(cct) << "error enabling mirroring for image "
+              << img_pair.first << ": " << cpp_strerror(r) << dendl;
+            rb_state.img_ctxs.push_back(std::make_pair(img_ctx, false));
+            return r;
+          }
+
+          rb_state.img_ctxs.push_back(std::make_pair(img_ctx, true));
+        }
+      }
+    }
+
+    rb_state.do_rollback = false;
+
     r = cls_client::mirror_mode_set(&io_ctx, next_mirror_mode);
     if (r < 0) {
       lderr(cct) << "Failed to set mirror mode: " << cpp_strerror(r) << dendl;
       return r;
     }
+
     return 0;
   }