#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 {
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;
}
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;
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;
{
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;
}
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;
}
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);
}
}