]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: use async image removal state machine
authorVenky Shankar <vshankar@redhat.com>
Wed, 24 Aug 2016 15:08:03 +0000 (20:38 +0530)
committerDongsheng Yang <dongsheng.yang@easystack.cn>
Thu, 23 Feb 2017 03:10:59 +0000 (11:10 +0800)
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/librbd/internal.cc

index 703e496e259e309ba17eaf172258e0c59bd68d73..175fc862ba3936220af323666c87e204258574eb 100644 (file)
@@ -35,6 +35,7 @@
 #include "librbd/exclusive_lock/AutomaticPolicy.h"
 #include "librbd/exclusive_lock/StandardPolicy.h"
 #include "librbd/image/CreateRequest.h"
+#include "librbd/image/RemoveRequest.h"
 #include "librbd/managed_lock/Types.h"
 #include "librbd/mirror/DisableRequest.h"
 #include "librbd/mirror/EnableRequest.h"
@@ -165,46 +166,6 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
   return 0;
 }
 
-void filter_out_mirror_watchers(ImageCtx *ictx,
-                                std::list<obj_watch_t> *watchers) {
-  if (watchers->empty()) {
-    return;
-  }
-
-  if ((ictx->features & RBD_FEATURE_JOURNALING) == 0) {
-    return;
-  }
-
-  cls::rbd::MirrorImage mirror_image;
-  int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, &mirror_image);
-  if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(ictx->cct) << "failed to retrieve mirroring state: "
-                       << cpp_strerror(r) << dendl;
-    }
-    return;
-  }
-
-  if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
-    return;
-  }
-
-  std::list<obj_watch_t> mirror_watchers;
-  r = ictx->md_ctx.list_watchers(RBD_MIRRORING, &mirror_watchers);
-  if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(ictx->cct) << "error listing mirroring watchers: "
-                       << cpp_strerror(r) << dendl;
-    }
-    return;
-  }
-  for (auto &watcher : mirror_watchers) {
-    watchers->remove_if([watcher] (obj_watch_t &w) {
-        return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
-      });
-  }
-}
-
 } // anonymous namespace
 
   int detect_format(IoCtx &io_ctx, const string &name,
@@ -1660,218 +1621,18 @@ void filter_out_mirror_watchers(ImageCtx *ictx,
     ldout(cct, 20) << "remove " << &io_ctx << " "
                    << (image_id.empty() ? image_name : image_id) << dendl;
 
-    std::string name(image_name);
-    std::string id(image_id);
-    bool old_format = false;
-    bool unknown_format = true;
-    ImageCtx *ictx = new ImageCtx(
-      (id.empty() ? name : std::string()), id, nullptr, io_ctx, false);
-    int r = ictx->state->open(true);
-    if (r < 0) {
-      ldout(cct, 2) << "error opening image: " << cpp_strerror(-r) << dendl;
-      delete ictx;
-      if (r != -ENOENT) {
-       return r;
-      }
-    } else {
-      string header_oid = ictx->header_oid;
-      old_format = ictx->old_format;
-      unknown_format = false;
-      name = ictx->name;
-      id = ictx->id;
-
-      ictx->owner_lock.get_read();
-      if (ictx->exclusive_lock != nullptr) {
-        if (force) {
-          // releasing read lock to avoid a deadlock when upgrading to
-          // write lock in the shut_down process
-          ictx->owner_lock.put_read();
-          if (ictx->exclusive_lock != nullptr) {
-            C_SaferCond ctx;
-            ictx->exclusive_lock->shut_down(&ctx);
-            r = ctx.wait();
-            if (r < 0) {
-              lderr(cct) << "error shutting down exclusive lock: "
-                         << cpp_strerror(r) << dendl;
-              ictx->state->close();
-              return r;
-            }
-            assert (ictx->exclusive_lock == nullptr);
-            ictx->owner_lock.get_read();
-          }
-        } else {
-          r = ictx->operations->prepare_image_update();
-          if (r < 0 || !ictx->exclusive_lock->is_lock_owner()) {
-           lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl;
-           ictx->owner_lock.put_read();
-           ictx->state->close();
-            return -EBUSY;
-          }
-        }
-      }
-
-      if (ictx->snaps.size()) {
-       lderr(cct) << "image has snapshots - not removing" << dendl;
-       ictx->owner_lock.put_read();
-       ictx->state->close();
-       return -ENOTEMPTY;
-      }
-
-      std::list<obj_watch_t> watchers;
-      r = io_ctx.list_watchers(header_oid, &watchers);
-      if (r < 0) {
-        lderr(cct) << "error listing watchers" << dendl;
-       ictx->owner_lock.put_read();
-        ictx->state->close();
-        return r;
-      }
-
-      // If an image is being bootstrapped by rbd-mirror, it implies
-      // that the rbd-mirror daemon currently has the image open.
-      // Permit removal if this is the case.
-      filter_out_mirror_watchers(ictx, &watchers);
-
-      if (watchers.size() > 1) {
-        lderr(cct) << "image has watchers - not removing" << dendl;
-       ictx->owner_lock.put_read();
-        ictx->state->close();
-        return -EBUSY;
-      }
-
-      cls::rbd::GroupSpec s;
-      r = cls_client::image_get_group(&io_ctx, header_oid, &s);
-      if (r < 0 && r != -EOPNOTSUPP) {
-        lderr(cct) << "error querying consistency group" << dendl;
-        ictx->owner_lock.put_read();
-        ictx->state->close();
-        return r;
-      } else if (s.is_valid()) {
-       lderr(cct) << "image is in a consistency group - not removing" << dendl;
-       ictx->owner_lock.put_read();
-       ictx->state->close();
-       return -EMLINK;
-      }
-
-      trim_image(ictx, 0, prog_ctx);
-
-      ictx->parent_lock.get_read();
-      // struct assignment
-      parent_info parent_info = ictx->parent_md;
-      ictx->parent_lock.put_read();
-
-      r = cls_client::remove_child(&ictx->md_ctx, RBD_CHILDREN,
-                                  parent_info.spec, id);
-      if (r < 0 && r != -ENOENT) {
-       lderr(cct) << "error removing child from children list" << dendl;
-       ictx->owner_lock.put_read();
-        ictx->state->close();
-       return r;
-      }
-
-      if (!old_format) {
-        r = mirror_image_disable_internal(ictx, force, !force);
-        if (r < 0 && r != -EOPNOTSUPP) {
-          lderr(cct) << "error disabling image mirroring: " << cpp_strerror(r)
-                     << dendl;
-          ictx->owner_lock.put_read();
-          ictx->state->close();
-          return r;
-        }
-      }
-
-      ictx->owner_lock.put_read();
-      ictx->state->close();
-
-      ldout(cct, 2) << "removing header..." << dendl;
-      r = io_ctx.remove(header_oid);
-      if (r < 0 && r != -ENOENT) {
-       lderr(cct) << "error removing header: " << cpp_strerror(-r) << dendl;
-       return r;
-      }
-    }
-
-    if (old_format || unknown_format) {
-      ldout(cct, 2) << "removing rbd image from v1 directory..." << dendl;
-      r = tmap_rm(io_ctx, name);
-      old_format = (r == 0);
-      if (r < 0 && !unknown_format) {
-        if (r != -ENOENT) {
-          lderr(cct) << "error removing image from v1 directory: "
-                     << cpp_strerror(-r) << dendl;
-        }
-       return r;
-      }
-    }
-    if (!old_format) {
-      if (id.empty()) {
-        ldout(cct, 5) << "attempting to determine image id" << dendl;
-        r = cls_client::dir_get_id(&io_ctx, RBD_DIRECTORY, name, &id);
-        if (r < 0 && r != -ENOENT) {
-          lderr(cct) << "error getting id of image" << dendl;
-          return r;
-        }
-      } else if (name.empty()) {
-        ldout(cct, 5) << "attempting to determine image name" << dendl;
-        r = cls_client::dir_get_name(&io_ctx, RBD_DIRECTORY, id, &name);
-        if (r < 0 && r != -ENOENT) {
-          lderr(cct) << "error getting name of image" << dendl;
-          return r;
-        }
-      }
-
-      if (!id.empty()) {
-       ldout(cct, 2) << "removing header..." << dendl;
-       r = io_ctx.remove(util::header_name(id));
-       if (r < 0 && r != -ENOENT) {
-         lderr(cct) << "error removing header: " << cpp_strerror(-r) << dendl;
-         return r;
-       }
-
-        ldout(cct, 10) << "removing journal..." << dendl;
-        r = Journal<>::remove(io_ctx, id);
-        if (r < 0 && r != -ENOENT) {
-          lderr(cct) << "error removing image journal" << dendl;
-          return r;
-        }
-
-        ldout(cct, 10) << "removing object map..." << dendl;
-        r = ObjectMap<>::remove(io_ctx, id);
-        if (r < 0 && r != -ENOENT) {
-          lderr(cct) << "error removing image object map" << dendl;
-          return r;
-        }
-
-        ldout(cct, 10) << "removing image from rbd_mirroring object..."
-                       << dendl;
-        r = cls_client::mirror_image_remove(&io_ctx, id);
-        if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) {
-          lderr(cct) << "failed to remove image from mirroring directory: "
-                     << cpp_strerror(r) << dendl;
-          return r;
-        }
-      }
-
-      ldout(cct, 2) << "removing id object..." << dendl;
-      r = io_ctx.remove(util::id_obj_name(name));
-      if (r < 0 && r != -ENOENT) {
-       lderr(cct) << "error removing id object: " << cpp_strerror(r)
-                   << dendl;
-       return r;
-      }
+    C_SaferCond cond;
+    ContextWQ op_work_queue("librbd::op_work_queue",
+                            cct->_conf->rbd_op_thread_timeout,
+                            ImageCtx::get_thread_pool_instance(cct));
+    librbd::image::RemoveRequest<> *req = librbd::image::RemoveRequest<>::create(
+      io_ctx, image_name, image_id, force, prog_ctx, &op_work_queue, &cond);
+    req->send();
 
-      ldout(cct, 2) << "removing rbd image from v2 directory..." << dendl;
-      r = cls_client::dir_remove_image(&io_ctx, RBD_DIRECTORY, name, id);
-      if (r < 0) {
-        if (r != -ENOENT) {
-          lderr(cct) << "error removing image from v2 directory: "
-                     << cpp_strerror(-r) << dendl;
-        }
-        return r;
-      }
-    }
+    int r = cond.wait();
+    op_work_queue.drain();
 
-    ldout(cct, 2) << "done." << dendl;
-    return 0;
+    return r;
   }
 
   int snap_list(ImageCtx *ictx, vector<snap_info_t>& snaps)