]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: rbd-mirroring: Disable image mirroring when pool-level mirroring is disabled
authorRicardo Dias <rdias@suse.com>
Tue, 22 Mar 2016 12:24:03 +0000 (12:24 +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>
Fixes: #15217
src/librbd/internal.cc

index 8de3d53bbced3882f95701b55437dbe4bd5ab177..3d2b6df7b81fa1f4fce0bdcb2d314f8c40717f43 100644 (file)
@@ -2779,6 +2779,34 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
     return 0;
   }
 
+  int list_mirror_images(IoCtx& io_ctx,
+                         std::set<std::string>& mirror_image_ids) {
+    CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+
+    std::string last_read = "";
+    int max_read = 1024;
+    int r;
+    do {
+      std::map<std::string, std::string> mirror_images;
+      r =  cls_client::mirror_image_list(&io_ctx, last_read, max_read,
+                                             &mirror_images);
+      if (r < 0) {
+        lderr(cct) << "error listing mirrored image directory: "
+             << cpp_strerror(r) << dendl;
+        return r;
+      }
+      for (auto it = mirror_images.begin(); it != mirror_images.end(); ++it) {
+        mirror_image_ids.insert(it->first);
+      }
+      if (!mirror_images.empty()) {
+        last_read = mirror_images.rbegin()->first;
+      }
+      r = mirror_images.size();
+    } while (r == max_read);
+
+    return 0;
+  }
+
   int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) {
     CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
     ldout(cct, 20) << __func__ << dendl;
@@ -2911,6 +2939,50 @@ int validate_mirroring_enabled(ImageCtx *ictx) {
             return r;
           }
 
+          rb_state.img_ctxs.push_back(std::make_pair(img_ctx, true));
+        }
+      }
+    } else if (next_mirror_mode == cls::rbd::MIRROR_MODE_DISABLED) {
+
+      std::set<std::string> image_ids;
+      r = list_mirror_images(io_ctx, image_ids);
+      if (r < 0) {
+        lderr(cct) << "Failed listing images: " << cpp_strerror(r) << dendl;
+        return r;
+      }
+
+      for (const auto& img_id : image_ids) {
+        if (current_mirror_mode == cls::rbd::MIRROR_MODE_IMAGE) {
+          cls::rbd::MirrorImage mirror_image;
+          r = cls_client::mirror_image_get(&io_ctx, img_id, &mirror_image);
+          if (r < 0 && r != -ENOENT) {
+            lderr(cct) << "failed to retrieve mirroring state for image id "
+              << img_id << ": " << cpp_strerror(r) << dendl;
+            return r;
+          }
+          if (mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+            lderr(cct) << "Failed to disable mirror mode: there are still "
+              "images with mirroring enabled" << dendl;
+            return -EINVAL;
+          }
+        } else {
+          ImageCtx *img_ctx = new ImageCtx("", img_id, nullptr, io_ctx, false);
+          r = img_ctx->state->open();
+          if (r < 0) {
+            lderr(cct) << "error opening image id "<< img_id << ": "
+              << cpp_strerror(r) << dendl;
+            delete img_ctx;
+            return r;
+          }
+
+          r = mirror_image_disable(img_ctx, false);
+          if (r < 0) {
+            lderr(cct) << "error disabling mirroring for image id " << img_id
+              << 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));
         }
       }