]> 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)
committerJason Dillaman <dillaman@redhat.com>
Wed, 10 Mar 2021 20:15:26 +0000 (15:15 -0500)
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>
src/librbd/api/Trash.cc

index 0d8496e62e7889608d550dbe9e6991ab14effe31..6869d5a84a1c139b8b62af0d044d4dd6be3b814e 100644 (file)
@@ -25,6 +25,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
@@ -288,15 +289,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);
 }