#include "librbd/Utils.h"
#include "librbd/api/Config.h"
#include "librbd/api/Trash.h"
-#include "librbd/image/RemoveRequest.h"
#include "librbd/image/CloneRequest.h"
+#include "librbd/image/RemoveRequest.h"
+#include "librbd/image/PreRemoveRequest.h"
#include <boost/scope_exit.hpp>
#define dout_subsys ceph_subsys_rbd
return false;
}
+template <typename I>
+int pre_remove_image(librados::IoCtx& io_ctx, const std::string& image_id) {
+ I *image_ctx = I::create("", image_id, nullptr, io_ctx, false);
+ int r = image_ctx->state->open(OPEN_FLAG_SKIP_OPEN_PARENT);
+ if (r < 0) {
+ return r;
+ }
+
+ C_SaferCond ctx;
+ auto req = image::PreRemoveRequest<I>::create(image_ctx, false, &ctx);
+ req->send();
+
+ r = ctx.wait();
+ image_ctx->state->close();
+ return r;
+}
} // anonymous namespace
trash_image_source = RBD_TRASH_IMAGE_SOURCE_USER;
expire_seconds = config.get_val<uint64_t>(
"rbd_move_to_trash_on_remove_expire_seconds");
+ } else {
+ // attempt to pre-validate the removal before moving to trash and
+ // removing
+ r = pre_remove_image<I>(io_ctx, image_id);
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ }
}
r = Trash<I>::move(io_ctx, trash_image_source, image_name, image_id,
} else if (r < 0 && r != -EOPNOTSUPP) {
return r;
}
+
+ // fall-through if trash isn't supported
}
ThreadPool *thread_pool;
ASSERT_EQ(status.state, RBD_IMAGE_MIGRATION_STATE_PREPARED);
rbd_migration_status_cleanup(&status);
- ASSERT_EQ(-EINVAL, rbd_remove(ioctx, name.c_str()));
+ ASSERT_EQ(-EBUSY, rbd_remove(ioctx, name.c_str()));
ASSERT_EQ(-EINVAL, rbd_trash_move(ioctx, name.c_str(), 0));
ASSERT_EQ(0, rbd_migration_execute(ioctx, name.c_str()));
ASSERT_EQ(0, rbd_migration_prepare(ioctx, name.c_str(), ioctx,
new_name.c_str(), image_options));
- ASSERT_EQ(-EINVAL, rbd_remove(ioctx, new_name.c_str()));
+ ASSERT_EQ(-EBUSY, rbd_remove(ioctx, new_name.c_str()));
ASSERT_EQ(-EINVAL, rbd_trash_move(ioctx, new_name.c_str(), 0));
ASSERT_EQ(0, rbd_migration_abort(ioctx, name.c_str()));
ASSERT_NE(status.dest_image_id, "");
ASSERT_EQ(status.state, RBD_IMAGE_MIGRATION_STATE_PREPARED);
- ASSERT_EQ(-EINVAL, rbd.remove(ioctx, name.c_str()));
+ ASSERT_EQ(-EBUSY, rbd.remove(ioctx, name.c_str()));
ASSERT_EQ(-EINVAL, rbd.trash_move(ioctx, name.c_str(), 0));
ASSERT_EQ(0, rbd.migration_execute(ioctx, name.c_str()));
ASSERT_EQ(0, rbd.migration_prepare(ioctx, name.c_str(), ioctx,
new_name.c_str(), image_options));
- ASSERT_EQ(-EINVAL, rbd.remove(ioctx, new_name.c_str()));
+ ASSERT_EQ(-EBUSY, rbd.remove(ioctx, new_name.c_str()));
ASSERT_EQ(-EINVAL, rbd.trash_move(ioctx, new_name.c_str(), 0));
ASSERT_EQ(0, rbd.migration_abort(ioctx, name.c_str()));