]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/librbd/api/Image.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / librbd / api / Image.cc
index 7df0f4fc69e2e85e04a40e46131ed5abdb0b6ed5..b887ecdae75e13f56726c83d6f41036d71e6798a 100644 (file)
 #include "librbd/image/PreRemoveRequest.h"
 #include "librbd/io/ImageDispatcherInterface.h"
 #include "librbd/io/ObjectDispatcherInterface.h"
+#include "librbd/io/AioCompletion.h"
+#include "librbd/io/ImageDispatchSpec.h"
 #include <boost/scope_exit.hpp>
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
 #define dout_prefix *_dout << "librbd::api::Image: " << __func__ << ": "
 
+using std::map;
+using std::string;
 using librados::snap_t;
 
 namespace librbd {
@@ -309,14 +313,15 @@ int Image<I>::list_descendants(
     std::vector<librbd::linked_image_spec_t> *images) {
   ImageCtx *ictx = new librbd::ImageCtx("", image_id, nullptr,
                                         io_ctx, true);
+  CephContext *cct = ictx->cct;
   int r = ictx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT);
   if (r < 0) {
     if (r == -ENOENT) {
       return 0;
     }
-    lderr(ictx->cct) << "failed to open descendant " << image_id
-                     << " from pool " << io_ctx.get_pool_name() << ":"
-                     << cpp_strerror(r) << dendl;
+    lderr(cct) << "failed to open descendant " << image_id
+               << " from pool " << io_ctx.get_pool_name() << ":"
+               << cpp_strerror(r) << dendl;
     return r;
   }
 
@@ -324,9 +329,9 @@ int Image<I>::list_descendants(
 
   int r1 = ictx->state->close();
   if (r1 < 0) {
-    lderr(ictx->cct) << "error when closing descendant " << image_id
-                     << " from pool " << io_ctx.get_pool_name() << ":"
-                     << cpp_strerror(r) << dendl;
+    lderr(cct) << "error when closing descendant " << image_id
+               << " from pool " << io_ctx.get_pool_name() << ":"
+               << cpp_strerror(r1) << dendl;
   }
 
   return r;
@@ -677,6 +682,22 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx,
 template <typename I>
 int Image<I>::deep_copy(I *src, I *dest, bool flatten,
                         ProgressContext &prog_ctx) {
+  // ensure previous writes are visible to dest
+  C_SaferCond flush_ctx;
+  {
+    std::shared_lock owner_locker{src->owner_lock};
+    auto aio_comp = io::AioCompletion::create_and_start(&flush_ctx, src,
+                                                        io::AIO_TYPE_FLUSH);
+    auto req = io::ImageDispatchSpec::create_flush(
+      *src, io::IMAGE_DISPATCH_LAYER_INTERNAL_START,
+      aio_comp, io::FLUSH_SOURCE_INTERNAL, {});
+    req->send();
+  }
+  int r = flush_ctx.wait();
+  if (r < 0) {
+    return r;
+  }
+
   librados::snap_t snap_id_start = 0;
   librados::snap_t snap_id_end;
   {
@@ -693,7 +714,7 @@ int Image<I>::deep_copy(I *src, I *dest, bool flatten,
     src, dest, snap_id_start, snap_id_end, 0U, flatten, boost::none,
     asio_engine.get_work_queue(), &snap_seqs, &progress_handler, &cond);
   req->send();
-  int r = cond.wait();
+  r = cond.wait();
   if (r < 0) {
     return r;
   }
@@ -716,8 +737,7 @@ int Image<I>::snap_set(I *ictx,
   std::string name(snap_name == nullptr ? "" : snap_name);
   if (!name.empty()) {
     std::shared_lock image_locker{ictx->image_lock};
-    snap_id = ictx->get_snap_id(cls::rbd::UserSnapshotNamespace{},
-                                snap_name);
+    snap_id = ictx->get_snap_id(snap_namespace, snap_name);
     if (snap_id == CEPH_NOSNAP) {
       return -ENOENT;
     }
@@ -766,12 +786,24 @@ int Image<I>::remove(IoCtx& io_ctx, const std::string &image_name,
     r = Trash<I>::list(io_ctx, trash_entries, false);
     if (r < 0) {
       return r;
-    } else if (r >= 0) {
-      for (auto& entry : trash_entries) {
-        if (entry.name == image_name &&
-            entry.source == RBD_TRASH_IMAGE_SOURCE_REMOVING) {
-          return Trash<I>::remove(io_ctx, entry.id, true, prog_ctx);
+    }
+    for (auto& entry : trash_entries) {
+      if (entry.name == image_name &&
+          entry.source == RBD_TRASH_IMAGE_SOURCE_REMOVING) {
+        cls::rbd::TrashImageSpec spec;
+        r = cls_client::trash_get(&io_ctx, entry.id, &spec);
+        if (r < 0) {
+          lderr(cct) << "error getting image id " << entry.id
+                     << " info from trash: " << cpp_strerror(r) << dendl;
+          return r;
+        }
+        if (spec.state == cls::rbd::TRASH_IMAGE_STATE_MOVING) {
+          r = Trash<I>::move(io_ctx, entry.source, entry.name, entry.id, 0);
+          if (r < 0) {
+            return r;
+          }
         }
+        return Trash<I>::remove(io_ctx, entry.id, true, prog_ctx);
       }
     }