if (r == -ENOTEMPTY || r == -EBUSY || r == -EMLINK) {
// best-effort try to restore the image if the removal
// failed for possible expected reasons
- Trash<I>::restore(io_ctx, trash_image_source, image_id, image_name);
+ Trash<I>::restore(io_ctx, {cls::rbd::TRASH_IMAGE_SOURCE_REMOVING},
+ image_id, image_name);
}
}
return r;
int Migration<I>::v2_relink_src_image() {
ldout(m_cct, 10) << dendl;
- int r = Trash<I>::restore(m_src_io_ctx, RBD_TRASH_IMAGE_SOURCE_MIGRATION,
+ int r = Trash<I>::restore(m_src_io_ctx,
+ {cls::rbd::TRASH_IMAGE_SOURCE_MIGRATION},
m_src_image_ctx->id, m_src_image_ctx->name);
if (r < 0) {
lderr(m_cct) << "failed restoring image from trash: " << cpp_strerror(r)
namespace librbd {
namespace api {
+template <typename I>
+const typename Trash<I>::TrashImageSources Trash<I>::RESTORE_SOURCE_WHITELIST {
+ cls::rbd::TRASH_IMAGE_SOURCE_USER,
+ cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING
+ };
+
namespace {
template <typename I>
}
template <typename I>
-int Trash<I>::restore(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
+int Trash<I>::restore(librados::IoCtx &io_ctx,
+ const TrashImageSources& trash_image_sources,
const std::string &image_id,
const std::string &image_new_name) {
CephContext *cct((CephContext *)io_ctx.cct());
return r;
}
- if (trash_spec.source != static_cast<cls::rbd::TrashImageSource>(source)) {
- lderr(cct) << "Current trash source: " << trash_spec.source
- << " does not match expected: "
- << static_cast<cls::rbd::TrashImageSource>(source) << dendl;
+ if (trash_image_sources.count(trash_spec.source) == 0) {
+ lderr(cct) << "Current trash source '" << trash_spec.source << "' "
+ << "does not match expected: "
+ << trash_image_sources << dendl;
return -EINVAL;
}
#include "include/rados/librados_fwd.hpp"
#include "include/rbd/librbd.hpp"
+#include "cls/rbd/cls_rbd_types.h"
+#include <set>
#include <string>
#include <vector>
template <typename ImageCtxT = librbd::ImageCtx>
struct Trash {
+ typedef std::set<cls::rbd::TrashImageSource> TrashImageSources;
+ static const TrashImageSources RESTORE_SOURCE_WHITELIST;
static int move(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
const std::string &image_name, uint64_t delay);
float threshold, ProgressContext& pctx);
static int remove(librados::IoCtx &io_ctx, const std::string &image_id,
bool force, ProgressContext& prog_ctx);
- static int restore(librados::IoCtx &io_ctx, rbd_trash_image_source_t source,
+ static int restore(librados::IoCtx &io_ctx,
+ const TrashImageSources& trash_image_sources,
const std::string &image_id,
const std::string &image_new_name);
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
io_ctx.get_id(), id, name);
- int r = librbd::api::Trash<>::restore(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER,
- id, name);
+ int r = librbd::api::Trash<>::restore(
+ io_ctx, librbd::api::Trash<>::RESTORE_SOURCE_WHITELIST, id, name);
tracepoint(librbd, trash_undelete_exit, r);
return r;
}
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
tracepoint(librbd, trash_undelete_enter, io_ctx.get_pool_name().c_str(),
io_ctx.get_id(), id, name);
- int r = librbd::api::Trash<>::restore(io_ctx, RBD_TRASH_IMAGE_SOURCE_USER,
- id, name);
+ int r = librbd::api::Trash<>::restore(
+ io_ctx, librbd::api::Trash<>::RESTORE_SOURCE_WHITELIST, id, name);
tracepoint(librbd, trash_undelete_exit, r);
return r;
}
ASSERT_EQ(expected_images, images);
}
+TEST_F(TestTrash, RestoreMirroringSource) {
+ REQUIRE_FORMAT_V2();
+
+ librbd::RBD rbd;
+ librbd::Image image;
+ std::string image_id;
+ ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str()));
+ ASSERT_EQ(0, image.get_id(&image_id));
+ ASSERT_EQ(0, image.close());
+
+ ASSERT_EQ(0, api::Trash<>::move(m_ioctx, RBD_TRASH_IMAGE_SOURCE_MIRRORING,
+ m_image_name, 0));
+ ASSERT_EQ(0, rbd.trash_restore(m_ioctx, image_id.c_str(),
+ m_image_name.c_str()));
+}
+
} // namespace librbd