]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/api: allow an interrupted trash move to be restarted
authorJason Dillaman <dillaman@redhat.com>
Wed, 10 Mar 2021 20:15:26 +0000 (15:15 -0500)
committerNathan Cutler <ncutler@suse.com>
Thu, 8 Apr 2021 13:03:22 +0000 (15:03 +0200)
Search the trash entries for a matching image name that is
still in the moving state and allow the operation to be
restarted.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit ed2d696e1eafaa59d29ce6fac952e4e5f4f1e920)

src/librbd/api/Trash.cc

index a7aac5f2e22b635ba5f7033935a27c90fbe4c31c..092bf6e96b25f5f806416fca6dad6bc1709bba45 100644 (file)
@@ -24,6 +24,7 @@
 #include <json_spirit/json_spirit.h>
 #include "librbd/journal/DisabledPolicy.h"
 #include "librbd/image/ListWatchersRequest.h"
+#include <experimental/map>
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -280,15 +281,37 @@ int Trash<I>::move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
       return -EOPNOTSUPP;
     }
 
-    // image doesn't exist -- perhaps already in the trash since removing
-    // from the directory is the last step
-    return -ENOENT;
+    // search for an interrupted trash move request
+    std::map<std::string, cls::rbd::TrashImageSpec> trash_image_specs;
+    int r = list_trash_image_specs(io_ctx, &trash_image_specs, true);
+    if (r < 0) {
+      return r;
+    }
+
+    std::experimental::erase_if(
+      trash_image_specs, [image_name](const auto& pair) {
+        const auto& spec = pair.second;
+        return (spec.source != cls::rbd::TRASH_IMAGE_SOURCE_USER ||
+                spec.state != cls::rbd::TRASH_IMAGE_STATE_MOVING ||
+                spec.name != image_name);
+      });
+    if (trash_image_specs.empty()) {
+      return -ENOENT;
+    }
+
+    image_id = trash_image_specs.begin()->first;
+    ldout(cct, 15) << "derived image id " << image_id << " from existing "
+                   << "trash entry" << dendl;
   } else if (r < 0) {
     lderr(cct) << "failed to retrieve image id: " << cpp_strerror(r) << dendl;
     return r;
   }
 
-  ceph_assert(!image_name.empty() && !image_id.empty());
+  if (image_name.empty() || image_id.empty()) {
+    lderr(cct) << "invalid image name/id" << dendl;
+    return -EINVAL;
+  }
+
   return Trash<I>::move(io_ctx, source, image_name, image_id, delay);
 }