]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: add sparse copy support
authoryaoning <yaoning@unitedstack.com>
Thu, 9 Feb 2017 02:42:59 +0000 (10:42 +0800)
committerNing Yao <yaoning@unitedstack.com>
Tue, 4 Apr 2017 03:18:52 +0000 (03:18 +0000)
Fixes: fix issue #15648
http://tracker.ceph.com/issues/15648

Signed-off-by: yaoning <yaoning@unitedstack.com>
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/Utils.cc
src/librbd/Utils.h
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc
src/tools/rbd/action/Copy.cc
src/tools/rbd/action/Import.cc
src/tracing/librbd.tp

index 78168b62fce30917d2ecf01c0a8052b8c11b926a..115f90bfafec27be9f74200de36af7bb95532d36 100644 (file)
@@ -358,6 +358,9 @@ CEPH_RBD_API int rbd_copy(rbd_image_t image, rados_ioctx_t dest_io_ctx,
 CEPH_RBD_API int rbd_copy2(rbd_image_t src, rbd_image_t dest);
 CEPH_RBD_API int rbd_copy3(rbd_image_t src, rados_ioctx_t dest_io_ctx,
                           const char *destname, rbd_image_options_t dest_opts);
+CEPH_RBD_API int rbd_copy4(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+                          const char *destname, rbd_image_options_t dest_opts,
+                          size_t sparse_size);
 CEPH_RBD_API int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
                                         const char *destname,
                                         librbd_progress_fn_t cb, void *cbdata);
@@ -368,6 +371,12 @@ CEPH_RBD_API int rbd_copy_with_progress3(rbd_image_t image,
                                         const char *destname,
                                         rbd_image_options_t dest_opts,
                                         librbd_progress_fn_t cb, void *cbdata);
+CEPH_RBD_API 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 cb, void *cbdata,
+                                        size_t sparse_size);
 
 /* snapshots */
 CEPH_RBD_API int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
index 9110e6d896f9df16d5db1eb229c1b174eca259be..5d85ab77ffa4cfb6714de36a14ca0724a3e3979d 100644 (file)
@@ -254,11 +254,16 @@ public:
   int copy(IoCtx& dest_io_ctx, const char *destname);
   int copy2(Image& dest);
   int copy3(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts);
+  int copy4(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts,
+           size_t sparse_size);
   int copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
                         ProgressContext &prog_ctx);
   int copy_with_progress2(Image& dest, ProgressContext &prog_ctx);
   int copy_with_progress3(IoCtx& dest_io_ctx, const char *destname,
                          ImageOptions& opts, ProgressContext &prog_ctx);
+  int copy_with_progress4(IoCtx& dest_io_ctx, const char *destname,
+                         ImageOptions& opts, ProgressContext &prog_ctx,
+                         size_t sparse_size);
 
   /* striping */
   uint64_t get_stripe_unit() const;
index 5f449529f965babc39682b198c1396e916834c5b..dc6e7988e69c65169ad07ebbb0b5eb12fbff2229 100644 (file)
@@ -69,6 +69,35 @@ uint64_t get_rbd_default_features(CephContext* cct)
   return boost::lexical_cast<uint64_t>(str_val);
 }
 
+bool calc_sparse_extent(const bufferptr &bp,
+                        size_t sparse_size,
+                        uint64_t length,
+                        size_t *write_offset,
+                        size_t *write_length,
+                        size_t *offset) {
+  size_t extent_size;
+  if (*offset + sparse_size > length) {
+    extent_size = length - *offset;
+  } else {
+    extent_size = sparse_size;
+  }
+
+  bufferptr extent(bp, *offset, extent_size);
+  *offset += extent_size;
+
+  bool extent_is_zero = extent.is_zero();
+  if (!extent_is_zero) {
+    *write_length += extent_size;
+  }
+  if (extent_is_zero && *write_length == 0) {
+    *write_offset += extent_size;
+  }
+
+  if ((extent_is_zero || *offset == length) && *write_length != 0) {
+    return true;
+  }
+  return false;
+}
 } // namespace util
 
 } // namespace librbd
index 9d0c881248358a3d1c58e5e8a4bff86ba6a99477..ce98d3ad6e3c50d65554ccb1de947bce5776afc0 100644 (file)
@@ -187,6 +187,12 @@ private:
 
 uint64_t get_rbd_default_features(CephContext* cct);
 
+bool calc_sparse_extent(const bufferptr &bp,
+                        size_t sparse_size,
+                        uint64_t length,
+                        size_t *write_offset,
+                        size_t *write_length,
+                        size_t *offset);
 } // namespace util
 
 } // namespace librbd
index cfcec2bdde29f35da0d58db5213588ff75a1dc4e..dc8bd54ccec9cd0f4d0454a2dd005bad8cffdddd 100644 (file)
@@ -1443,7 +1443,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
   };
 
   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
@@ -1493,7 +1493,8 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
       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;
@@ -1503,22 +1504,23 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
 
   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 {
@@ -1537,13 +1539,47 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
        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:
@@ -1551,9 +1587,10 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
     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);
@@ -1595,7 +1632,7 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) {
 
       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}},
index 1c999f119022263b11f406a650d51e5186afbe58..b9ccdeec2d4eb7ab8e5afb1e5168a2d21f786e29 100644 (file)
@@ -152,8 +152,8 @@ namespace librbd {
   int snap_is_protected(ImageCtx *ictx, const char *snap_name,
                        bool *is_protected);
   int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname,
-          ImageOptions& opts, ProgressContext &prog_ctx);
-  int copy(ImageCtx *src, ImageCtx *dest, ProgressContext &prog_ctx);
+          ImageOptions& opts, ProgressContext &prog_ctx, size_t sparse_size);
+  int copy(ImageCtx *src, ImageCtx *dest, ProgressContext &prog_ctx, size_t sparse_size);
 
   /* cooperative locking */
   int list_lockers(ImageCtx *ictx,
index 8f20d2d1fe3da01f1fbc4323af6a12416c3c1638..cbc96bd6009973737b135bce0fffddf8dff87aa6 100644 (file)
@@ -962,7 +962,7 @@ namespace librbd {
     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;
   }
@@ -973,7 +973,7 @@ namespace librbd {
     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;
   }
@@ -983,18 +983,28 @@ namespace librbd {
     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;
   }
@@ -1004,7 +1014,7 @@ namespace librbd {
     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;
   }
@@ -1015,11 +1025,23 @@ namespace librbd {
   {
     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;
@@ -2099,7 +2121,7 @@ extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p,
   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;
 }
@@ -2110,7 +2132,7 @@ extern "C" int rbd_copy2(rbd_image_t srcp, rbd_image_t destp)
   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;
 }
@@ -2124,11 +2146,25 @@ extern "C" int rbd_copy3(rbd_image_t image, rados_ioctx_t dest_p,
   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)
@@ -2139,7 +2175,7 @@ extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
   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;
 }
@@ -2151,7 +2187,7 @@ extern "C" int rbd_copy_with_progress2(rbd_image_t srcp, rbd_image_t destp,
   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;
 }
@@ -2164,14 +2200,31 @@ extern "C" int rbd_copy_with_progress3(rbd_image_t image, rados_ioctx_t dest_p,
   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;
index e45b008abb8e4edc28cecc4e71edc05f7237ffeb..6d4fbceb92447ee3d82326af6bd9282592f4ce55 100644 (file)
@@ -17,10 +17,11 @@ namespace po = boost::program_options;
 
 static int do_copy(librbd::Image &src, librados::IoCtx& dest_pp,
                   const char *destname, librbd::ImageOptions& opts,
-                  bool no_progress)
+                  bool no_progress,
+                  size_t sparse_size)
 {
   utils::ProgressContext pc("Image copy", no_progress);
-  int r = src.copy_with_progress3(dest_pp, destname, opts, pc);
+  int r = src.copy_with_progress4(dest_pp, destname, opts, pc, sparse_size);
   if (r < 0){
     pc.fail();
     return r;
@@ -35,6 +36,7 @@ void get_arguments(po::options_description *positional,
                                      at::ARGUMENT_MODIFIER_SOURCE);
   at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
   at::add_create_image_options(options, false);
+  at::add_sparse_size_option(options);
   at::add_no_progress_option(options);
 }
 
@@ -82,8 +84,12 @@ int execute(const po::variables_map &vm) {
     return r;
   }
 
+  size_t sparse_size = utils::RBD_DEFAULT_SPARSE_SIZE;
+  if (vm.count(at::IMAGE_SPARSE_SIZE)) {
+    sparse_size = vm[at::IMAGE_SPARSE_SIZE].as<size_t>();
+  }
   r = do_copy(image, dst_io_ctx, dst_image_name.c_str(), opts,
-              vm[at::NO_PROGRESS].as<bool>());
+              vm[at::NO_PROGRESS].as<bool>(), sparse_size);
   if (r < 0) {
     std::cerr << "rbd: copy failed: " << cpp_strerror(r) << std::endl;
     return r;
index bcd733758764839f49a43f014570da5b65a0209f..db0f9e08fd1dffc13b9aa1880342812bb224b816 100644 (file)
@@ -621,7 +621,7 @@ static int do_import_v2(int fd, librbd::Image &image, uint64_t size,
 }
 
 static int do_import_v1(int fd, librbd::Image &image, uint64_t size,
-                        size_t imgblklen, utils::ProgressContext &pc
+                        size_t imgblklen, utils::ProgressContext &pc,
                        size_t sparse_size)
 {
   int r = 0;
index b3e1bd3740cabb227127649eebf73c44a6aaecdb..1df20396a3975d8eca0bc7046eb1952951e9e6bf 100644 (file)
@@ -820,6 +820,38 @@ TRACEPOINT_EVENT(librbd, copy3_exit,
     )
 )
 
+TRACEPOINT_EVENT(librbd, copy4_enter,
+    TP_ARGS(
+        void*, src_imagectx,
+        const char*, src_name,
+        const char*, src_snap_name,
+        char, src_read_only,
+        const char*, dst_pool_name,
+        uint64_t, dst_id,
+        const char*, dst_name,
+        void*, opts,
+        size_t, sparse_size),
+    TP_FIELDS(
+        ctf_integer_hex(void*, src_imagectx, src_imagectx)
+        ctf_string(src_name, src_name)
+        ctf_string(src_snap_name, src_snap_name)
+        ctf_integer(char, src_read_only, src_read_only)
+        ctf_string(dst_pool_name, dst_pool_name)
+        ctf_integer(uint64_t, dst_id, dst_id)
+        ctf_string(dst_name, dst_name)
+        ctf_integer_hex(void*, opts, opts)
+        ctf_integer(size_t, sparse_size, sparse_size)
+    )
+)
+
+TRACEPOINT_EVENT(librbd, copy4_exit,
+    TP_ARGS(
+        int, retval),
+    TP_FIELDS(
+        ctf_integer(int, retval, retval)
+    )
+)
+
 TRACEPOINT_EVENT(librbd, resize_enter,
     TP_ARGS(
         void*, imagectx,