]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: introduce a new flag of RBD_SNAP_REMOVE_FLATTEN
authorDongsheng Yang <dongsheng.yang@easystack.cn>
Fri, 1 Jul 2016 07:06:22 +0000 (03:06 -0400)
committerDongsheng Yang <dongsheng.yang@easystack.cn>
Tue, 26 Jul 2016 06:23:30 +0000 (02:23 -0400)
introduce RBD_SNAP_REMOVE_FLATTEN for flags of Image::snap_remove2()
to auto flatten the children of snapshot which we want to remove.

Signed-off-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
src/include/rbd/librbd.h
src/librbd/internal.cc

index 2a9a84d2b333b3c066602d8f5c83ecb92fb745b3..656703bc92fa04113fda52cc60d31e0ec012efc1 100644 (file)
@@ -73,6 +73,8 @@ typedef struct {
 #define RBD_MAX_BLOCK_NAME_SIZE 24
 
 #define RBD_SNAP_REMOVE_UNPROTECT      1 << 0
+#define RBD_SNAP_REMOVE_FLATTEN                1 << 1
+#define RBD_SNAP_REMOVE_FORCE          (RBD_SNAP_REMOVE_UNPROTECT | RBD_SNAP_REMOVE_FLATTEN)
 
 /**
  * These types used to in set_image_notification to indicate the type of event
index 4d64dde6ab6f2395ceea22ca01c93249e9d45e11..ef945acba1334673dbaf566e28aba28140858e0e 100644 (file)
@@ -865,6 +865,69 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
     return 0;
   }
 
+  int flatten_children(ImageCtx *ictx, const char* snap_name)
+  {
+    CephContext *cct = ictx->cct;
+    ldout(cct, 20) << "children flatten " << ictx->name << dendl;
+
+    RWLock::RLocker l(ictx->snap_lock);
+    snap_t snap_id = ictx->get_snap_id(snap_name);
+    parent_spec parent_spec(ictx->md_ctx.get_id(), ictx->id, snap_id);
+    map< pair<int64_t, string>, set<string> > image_info;
+
+    int r = list_children_info(ictx, parent_spec, image_info);
+    if (r < 0) {
+      return r;
+    }
+
+    Rados rados(ictx->md_ctx);
+    for ( auto &info : image_info){
+      string pool = info.first.second;
+      IoCtx ioctx;
+      r = rados.ioctx_create2(info.first.first, ioctx);
+      if (r < 0) {
+        lderr(cct) << "Error accessing child image pool " << pool
+                   << dendl;
+        return r;
+      }
+
+      for (auto &id_it : info.second) {
+       ImageCtx *imctx = new ImageCtx("", id_it, NULL, ioctx, false);
+       int r = imctx->state->open();
+       if (r < 0) {
+         lderr(cct) << "error opening image: "
+                    << cpp_strerror(r) << dendl;
+         return r;
+       }
+       librbd::NoOpProgressContext prog_ctx;
+       r = imctx->operations->flatten(prog_ctx);
+       if (r < 0) {
+         lderr(cct) << "error to flatten image: " << pool << "/" << id_it
+                    << cpp_strerror(r) << dendl;
+         return r;
+       }
+
+       if ((imctx->features & RBD_FEATURE_DEEP_FLATTEN) == 0 &&
+           !imctx->snaps.empty()) {
+         imctx->parent_lock.get_read();
+         parent_info parent_info = imctx->parent_md;
+         imctx->parent_lock.put_read();
+
+         r = cls_client::remove_child(&imctx->md_ctx, RBD_CHILDREN,
+                                      parent_info.spec, imctx->id);
+         if (r < 0 && r != -ENOENT) {
+           lderr(cct) << "error removing child from children list" << dendl;
+           imctx->state->close();
+           return r;
+         }
+       }
+       imctx->state->close();
+      }
+    }
+    
+    return 0;
+  }
+
   int list_children(ImageCtx *ictx, set<pair<string, string> >& names)
   {
     CephContext *cct = ictx->cct;
@@ -2270,23 +2333,27 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
 
     int r = 0;
 
-retry:
     r = ictx->state->refresh_if_required();
     if (r < 0)
       return r;
 
+    if (flags & RBD_SNAP_REMOVE_FLATTEN) {
+       r = flatten_children(ictx, snap_name);
+       if (r < 0) {
+         return r;
+       }
+    }
+
+    if (flags & RBD_SNAP_REMOVE_UNPROTECT) {
+      r = ictx->operations->snap_unprotect(snap_name);
+      if (r < 0)
+       return r;
+    }
+
     C_SaferCond ctx;
     ictx->operations->snap_remove(snap_name, &ctx);
 
     r = ctx.wait();
-    if (r < 0) {
-      if (r == -EBUSY && (flags & RBD_SNAP_REMOVE_UNPROTECT)) {
-       r = ictx->operations->snap_unprotect(snap_name);
-       goto retry;
-      }
-      return r;
-    }
-
     return r;
   }