};
int copy(ImageCtx *src, IoCtx& dest_md_ctx, const char *destname,
- ImageOptions& opts, ProgressContext &prog_ctx)
+ ImageOptions& opts, ProgressContext &prog_ctx, size_t sparse_size)
{
CephContext *cct = (CephContext *)dest_md_ctx.cct();
ldout(cct, 20) << "copy " << src->name
return r;
}
- r = copy(src, dest, prog_ctx);
+ r = copy(src, dest, prog_ctx, sparse_size);
+
int close_r = dest->state->close();
if (r == 0 && close_r < 0) {
r = close_r;
class C_CopyWrite : public Context {
public:
- C_CopyWrite(SimpleThrottle *throttle, bufferlist *bl)
- : m_throttle(throttle), m_bl(bl) {}
+ C_CopyWrite(bufferlist *bl, Context* ctx)
+ : m_bl(bl), m_ctx(ctx) {}
void finish(int r) override {
delete m_bl;
- m_throttle->end_op(r);
+ m_ctx->complete(r);
}
private:
- SimpleThrottle *m_throttle;
bufferlist *m_bl;
+ Context *m_ctx;
};
class C_CopyRead : public Context {
public:
C_CopyRead(SimpleThrottle *throttle, ImageCtx *dest, uint64_t offset,
- bufferlist *bl)
- : m_throttle(throttle), m_dest(dest), m_offset(offset), m_bl(bl) {
+ bufferlist *bl, size_t sparse_size)
+ : m_throttle(throttle), m_dest(dest), m_offset(offset), m_bl(bl),
+ m_sparse_size(sparse_size) {
m_throttle->start_op();
}
void finish(int r) override {
return;
}
- Context *ctx = new C_CopyWrite(m_throttle, m_bl);
- auto comp = io::AioCompletion::create(ctx);
+ if (!m_sparse_size) {
+ m_sparse_size = (1 << m_dest->order);
+ }
- // coordinate through AIO WQ to ensure lock is acquired if needed
- m_dest->io_work_queue->aio_write(comp, m_offset, m_bl->length(),
- std::move(*m_bl),
- LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ auto *throttle = m_throttle;
+ auto *end_op_ctx = new FunctionContext([throttle](int r) {
+ throttle->end_op(r);
+ });
+ auto gather_ctx = new C_Gather(m_dest->cct, end_op_ctx);
+
+ bufferptr m_ptr(m_bl->length());
+ m_bl->rebuild(m_ptr);
+ size_t write_offset = 0;
+ size_t write_length = 0;
+ size_t offset = 0;
+ size_t length = m_bl->length();
+ while (offset < length) {
+ if (util::calc_sparse_extent(m_ptr,
+ m_sparse_size,
+ length,
+ &write_offset,
+ &write_length,
+ &offset)) {
+ bufferptr write_ptr(m_ptr, write_offset, write_length);
+ bufferlist *write_bl = new bufferlist();
+ write_bl->push_back(write_ptr);
+ Context *ctx = new C_CopyWrite(write_bl, gather_ctx->new_sub());
+ auto comp = io::AioCompletion::create(ctx);
+
+ // coordinate through AIO WQ to ensure lock is acquired if needed
+ m_dest->io_work_queue->aio_write(comp, m_offset + write_offset,
+ write_length,
+ std::move(*write_bl),
+ LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
+ write_offset = offset;
+ write_length = 0;
+ }
+ }
+ delete m_bl;
+ assert(gather_ctx->get_sub_created_count() > 0);
+ gather_ctx->activate();
}
private:
ImageCtx *m_dest;
uint64_t m_offset;
bufferlist *m_bl;
+ size_t m_sparse_size;
};
- int copy(ImageCtx *src, ImageCtx *dest, ProgressContext &prog_ctx)
+ int copy(ImageCtx *src, ImageCtx *dest, ProgressContext &prog_ctx, size_t sparse_size)
{
src->snap_lock.get_read();
uint64_t src_size = src->get_image_size(src->snap_id);
uint64_t len = min(period, src_size - offset);
bufferlist *bl = new bufferlist();
- Context *ctx = new C_CopyRead(&throttle, dest, offset, bl);
+ Context *ctx = new C_CopyRead(&throttle, dest, offset, bl, sparse_size);
auto comp = io::AioCompletion::create_and_start(ctx, src,
io::AIO_TYPE_READ);
io::ImageRequest<>::aio_read(src, comp, {{offset, len}},
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
ImageOptions opts;
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
tracepoint(librbd, copy_exit, r);
return r;
}
ImageCtx *destctx = (ImageCtx *)dest.ctx;
tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(srcctx, destctx, prog_ctx);
+ int r = librbd::copy(srcctx, destctx, prog_ctx, 0);
tracepoint(librbd, copy2_exit, r);
return r;
}
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
tracepoint(librbd, copy3_exit, r);
return r;
}
+ int Image::copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts, size_t sparse_size)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
+ librbd::NoOpProgressContext prog_ctx;
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, sparse_size);
+ tracepoint(librbd, copy4_exit, r);
+ return r;
+ }
+
int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
librbd::ProgressContext &pctx)
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
ImageOptions opts;
- int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
tracepoint(librbd, copy_exit, r);
return r;
}
ImageCtx *srcctx = (ImageCtx *)ctx;
ImageCtx *destctx = (ImageCtx *)dest.ctx;
tracepoint(librbd, copy2_enter, srcctx, srcctx->name.c_str(), srcctx->snap_name.c_str(), srcctx->read_only, destctx, destctx->name.c_str(), destctx->snap_name.c_str(), destctx->read_only);
- int r = librbd::copy(srcctx, destctx, pctx);
+ int r = librbd::copy(srcctx, destctx, pctx, 0);
tracepoint(librbd, copy2_exit, r);
return r;
}
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts);
- int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, 0);
tracepoint(librbd, copy3_exit, r);
return r;
}
+ int Image::copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
+ ImageOptions& opts,
+ librbd::ProgressContext &pctx,
+ size_t sparse_size)
+ {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+ tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, opts.opts, sparse_size);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, pctx, sparse_size);
+ tracepoint(librbd, copy4_exit, r);
+ return r;
+ }
+
int Image::flatten()
{
ImageCtx *ictx = (ImageCtx *)ctx;
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
librbd::ImageOptions opts;
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
tracepoint(librbd, copy_exit, r);
return r;
}
librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(src, dest, prog_ctx);
+ int r = librbd::copy(src, dest, prog_ctx, 0);
tracepoint(librbd, copy2_exit, r);
return r;
}
tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts);
librbd::ImageOptions c_opts_(c_opts);
librbd::NoOpProgressContext prog_ctx;
- int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx);
+ int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, 0);
tracepoint(librbd, copy3_exit, r);
return r;
}
+extern "C" int rbd_copy4(rbd_image_t image, rados_ioctx_t dest_p,
+ const char *destname, rbd_image_options_t c_opts, size_t sparse_size)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ librados::IoCtx dest_io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+ tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, c_opts, sparse_size);
+ librbd::ImageOptions c_opts_(c_opts);
+ librbd::NoOpProgressContext prog_ctx;
+ int r = librbd::copy(ictx, dest_io_ctx, destname, c_opts_, prog_ctx, sparse_size);
+ tracepoint(librbd, copy4_exit, r);
+ return r;
+}
+
extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
const char *destname,
librbd_progress_fn_t fn, void *data)
tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
librbd::ImageOptions opts;
librbd::CProgressContext prog_ctx(fn, data);
- int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx);
+ int ret = librbd::copy(ictx, dest_io_ctx, destname, opts, prog_ctx, 0);
tracepoint(librbd, copy_exit, ret);
return ret;
}
librbd::ImageCtx *dest = (librbd::ImageCtx *)destp;
tracepoint(librbd, copy2_enter, src, src->name.c_str(), src->snap_name.c_str(), src->read_only, dest, dest->name.c_str(), dest->snap_name.c_str(), dest->read_only);
librbd::CProgressContext prog_ctx(fn, data);
- int ret = librbd::copy(src, dest, prog_ctx);
+ int ret = librbd::copy(src, dest, prog_ctx, 0);
tracepoint(librbd, copy2_exit, ret);
return ret;
}
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
librados::IoCtx dest_io_ctx;
librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
- tracepoint(librbd, copy_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname);
+ tracepoint(librbd, copy3_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts);
librbd::ImageOptions dest_opts_(dest_opts);
librbd::CProgressContext prog_ctx(fn, data);
- int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx);
- tracepoint(librbd, copy_exit, ret);
+ int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, 0);
+ tracepoint(librbd, copy3_exit, ret);
+ return ret;
+}
+
+extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
+ const char *destname,
+ rbd_image_options_t dest_opts,
+ librbd_progress_fn_t fn, void *data, size_t sparse_size)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+ librados::IoCtx dest_io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+ tracepoint(librbd, copy4_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, dest_io_ctx.get_pool_name().c_str(), dest_io_ctx.get_id(), destname, dest_opts, sparse_size);
+ librbd::ImageOptions dest_opts_(dest_opts);
+ librbd::CProgressContext prog_ctx(fn, data);
+ int ret = librbd::copy(ictx, dest_io_ctx, destname, dest_opts_, prog_ctx, sparse_size);
+ tracepoint(librbd, copy4_exit, ret);
return ret;
}
+
extern "C" int rbd_flatten(rbd_image_t image)
{
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;