]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: add deep_copy function to API
authorMykola Golub <to.my.trociny@gmail.com>
Tue, 31 Oct 2017 20:56:07 +0000 (22:56 +0200)
committerMykola Golub <to.my.trociny@gmail.com>
Mon, 6 Nov 2017 08:29:44 +0000 (10:29 +0200)
Signed-off-by: Mykola Golub <to.my.trociny@gmail.com>
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/librbd.cc
src/test/librbd/test_librbd.cc
src/tracing/librbd.tp

index a7f09b10afad2432331e1eae0cafb9960621345c..23c166a58f5bb4e3883936d0bcd8e52d98847424 100644 (file)
@@ -432,6 +432,17 @@ CEPH_RBD_API int rbd_copy_with_progress4(rbd_image_t image,
                                         librbd_progress_fn_t cb, void *cbdata,
                                         size_t sparse_size);
 
+/* deep copy */
+CEPH_RBD_API int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+                               const char *destname,
+                               rbd_image_options_t dest_opts);
+CEPH_RBD_API int rbd_deep_copy_with_progress(rbd_image_t image,
+                                             rados_ioctx_t dest_io_ctx,
+                                             const char *destname,
+                                             rbd_image_options_t dest_opts,
+                                             librbd_progress_fn_t cb,
+                                             void *cbdata);
+
 /* snapshots */
 CEPH_RBD_API int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
                                int *max_snaps);
index bbf4270bc245d7b13bd1eb4a5700acc3eccf7054..7e9825d2d45c8bf18e64f61fca1b6cc412464a91 100644 (file)
@@ -293,6 +293,11 @@ public:
                          ImageOptions& opts, ProgressContext &prog_ctx,
                          size_t sparse_size);
 
+  /* deep copy */
+  int deep_copy(IoCtx& dest_io_ctx, const char *destname, ImageOptions& opts);
+  int deep_copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
+                              ImageOptions& opts, ProgressContext &prog_ctx);
+
   /* striping */
   uint64_t get_stripe_unit() const;
   uint64_t get_stripe_count() const;
index c71aa7697c44561a13b385686727a4ba4d0cdced..ddb6ef17769a15b209af2a4f5e248155e05da1dc 100644 (file)
@@ -29,6 +29,7 @@
 #include "librbd/Operations.h"
 #include "librbd/api/DiffIterate.h"
 #include "librbd/api/Group.h"
+#include "librbd/api/Image.h"
 #include "librbd/api/Mirror.h"
 #include "librbd/io/AioCompletion.h"
 #include "librbd/io/ImageRequestWQ.h"
@@ -1238,6 +1239,36 @@ namespace librbd {
     return r;
   }
 
+  int Image::deep_copy(IoCtx& dest_io_ctx, const char *destname,
+                       ImageOptions& opts)
+  {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+    tracepoint(librbd, deep_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, opts.opts);
+    librbd::NoOpProgressContext prog_ctx;
+    int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
+                                            prog_ctx);
+    tracepoint(librbd, deep_copy_exit, r);
+    return r;
+  }
+
+  int Image::deep_copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
+                                     ImageOptions& opts,
+                                     librbd::ProgressContext &prog_ctx)
+  {
+    ImageCtx *ictx = (ImageCtx *)ctx;
+    tracepoint(librbd, deep_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, opts.opts);
+    int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
+                                            prog_ctx);
+    tracepoint(librbd, deep_copy_exit, r);
+    return r;
+  }
+
   int Image::flatten()
   {
     ImageCtx *ictx = (ImageCtx *)ctx;
@@ -2572,6 +2603,44 @@ extern "C" int rbd_copy_with_progress4(rbd_image_t image, rados_ioctx_t dest_p,
   return ret;
 }
 
+extern "C" int rbd_deep_copy(rbd_image_t image, rados_ioctx_t dest_p,
+                             const char *destname, rbd_image_options_t c_opts)
+{
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+  librados::IoCtx dest_io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+  tracepoint(librbd, deep_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, c_opts);
+  librbd::ImageOptions opts(c_opts);
+  librbd::NoOpProgressContext prog_ctx;
+  int r = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
+                                          prog_ctx);
+  tracepoint(librbd, deep_copy_exit, r);
+  return r;
+}
+
+extern "C" int rbd_deep_copy_with_progress(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)
+{
+  librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+  librados::IoCtx dest_io_ctx;
+  librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
+  tracepoint(librbd, deep_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, dest_opts);
+  librbd::ImageOptions opts(dest_opts);
+  librbd::CProgressContext prog_ctx(fn, data);
+  int ret = librbd::api::Image<>::deep_copy(ictx, dest_io_ctx, destname, opts,
+                                            prog_ctx);
+  tracepoint(librbd, deep_copy_exit, ret);
+  return ret;
+}
 
 extern "C" int rbd_flatten(rbd_image_t image)
 {
index 514b8b3fb8aa2c1b9c1c38f80ddc71d10e23b731..36b32b5587e85490f63e266a4d594156f1fdda94 100644 (file)
@@ -1079,6 +1079,173 @@ TEST_F(TestLibRBD, TestCopyPP)
   ioctx.close();
 }
 
+TEST_F(TestLibRBD, TestDeepCopy)
+{
+  REQUIRE_FORMAT_V2();
+
+  rados_ioctx_t ioctx;
+  rados_ioctx_create(_cluster, create_pool(true).c_str(), &ioctx);
+  BOOST_SCOPE_EXIT_ALL( (&ioctx) ) {
+    rados_ioctx_destroy(ioctx);
+  };
+
+  rbd_image_t image;
+  rbd_image_t image2;
+  rbd_image_t image3;
+  int order = 0;
+  std::string name = get_temp_image_name();
+  std::string name2 = get_temp_image_name();
+  std::string name3 = get_temp_image_name();
+
+  uint64_t size = 2 << 20;
+
+  rbd_image_options_t opts;
+  rbd_image_options_create(&opts);
+  BOOST_SCOPE_EXIT_ALL( (&opts) ) {
+    rbd_image_options_destroy(opts);
+  };
+
+  ASSERT_EQ(0, create_image(ioctx, name.c_str(), size, &order));
+  ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
+  BOOST_SCOPE_EXIT_ALL( (&image) ) {
+    ASSERT_EQ(0, rbd_close(image));
+  };
+  ASSERT_EQ(1, test_ls(ioctx, 1, name.c_str()));
+
+  size_t sum_key_len = 0;
+  size_t sum_value_len = 0;
+  std::string key;
+  std::string val;
+  for (int i = 1; i <= 70; i++) {
+    key = "key" + stringify(i);
+    val = "value" + stringify(i);
+    ASSERT_EQ(0, rbd_metadata_set(image, key.c_str(), val.c_str()));
+
+    sum_key_len += (key.size() + 1);
+    sum_value_len += (val.size() + 1);
+  }
+
+  char keys[1024];
+  char vals[1024];
+  size_t keys_len = sizeof(keys);
+  size_t vals_len = sizeof(vals);
+
+  char value[1024];
+  size_t value_len = sizeof(value);
+
+  ASSERT_EQ(0, rbd_deep_copy(image, ioctx, name2.c_str(), opts));
+  ASSERT_EQ(2, test_ls(ioctx, 2, name.c_str(), name2.c_str()));
+  ASSERT_EQ(0, rbd_open(ioctx, name2.c_str(), &image2, NULL));
+  BOOST_SCOPE_EXIT_ALL( (&image2) ) {
+    ASSERT_EQ(0, rbd_close(image2));
+  };
+  ASSERT_EQ(0, rbd_metadata_list(image2, "", 70, keys, &keys_len, vals,
+                                 &vals_len));
+  ASSERT_EQ(keys_len, sum_key_len);
+  ASSERT_EQ(vals_len, sum_value_len);
+
+  for (int i = 1; i <= 70; i++) {
+    key = "key" + stringify(i);
+    val = "value" + stringify(i);
+    ASSERT_EQ(0, rbd_metadata_get(image2, key.c_str(), value, &value_len));
+    ASSERT_STREQ(val.c_str(), value);
+
+    value_len = sizeof(value);
+  }
+
+  ASSERT_EQ(0, rbd_deep_copy_with_progress(image, ioctx, name3.c_str(), opts,
+                                           print_progress_percent, NULL));
+  ASSERT_EQ(3, test_ls(ioctx, 3, name.c_str(), name2.c_str(), name3.c_str()));
+
+  keys_len = sizeof(keys);
+  vals_len = sizeof(vals);
+  ASSERT_EQ(0, rbd_open(ioctx, name3.c_str(), &image3, NULL));
+  BOOST_SCOPE_EXIT_ALL( (&image3) ) {
+    ASSERT_EQ(0, rbd_close(image3));
+  };
+  ASSERT_EQ(0, rbd_metadata_list(image3, "", 70, keys, &keys_len, vals,
+                                 &vals_len));
+  ASSERT_EQ(keys_len, sum_key_len);
+  ASSERT_EQ(vals_len, sum_value_len);
+
+  for (int i = 1; i <= 70; i++) {
+    key = "key" + stringify(i);
+    val = "value" + stringify(i);
+    ASSERT_EQ(0, rbd_metadata_get(image3, key.c_str(), value, &value_len));
+    ASSERT_STREQ(val.c_str(), value);
+
+    value_len = sizeof(value);
+  }
+}
+
+TEST_F(TestLibRBD, TestDeepCopyPP)
+{
+  REQUIRE_FORMAT_V2();
+
+  librados::IoCtx ioctx;
+  ASSERT_EQ(0, _rados.ioctx_create(create_pool(true).c_str(), ioctx));
+
+  {
+    librbd::RBD rbd;
+    librbd::Image image;
+    librbd::Image image2;
+    librbd::Image image3;
+    int order = 0;
+    std::string name = get_temp_image_name();
+    std::string name2 = get_temp_image_name();
+    std::string name3 = get_temp_image_name();
+    uint64_t size = 2 << 20;
+    librbd::ImageOptions opts;
+    PrintProgress pp;
+
+    ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order));
+    ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
+
+    std::string key;
+    std::string val;
+    for (int i = 1; i <= 70; i++) {
+      key = "key" + stringify(i);
+      val = "value" + stringify(i);
+      ASSERT_EQ(0, image.metadata_set(key, val));
+    }
+
+    ASSERT_EQ(1, test_ls_pp(rbd, ioctx, 1, name.c_str()));
+    ASSERT_EQ(0, image.deep_copy(ioctx, name2.c_str(), opts));
+    ASSERT_EQ(2, test_ls_pp(rbd, ioctx, 2, name.c_str(), name2.c_str()));
+    ASSERT_EQ(0, rbd.open(ioctx, image2, name2.c_str(), NULL));
+
+    map<string, bufferlist> pairs;
+    std::string value;
+    ASSERT_EQ(0, image2.metadata_list("", 70, &pairs));
+    ASSERT_EQ(70U, pairs.size());
+
+    for (int i = 1; i <= 70; i++) {
+      key = "key" + stringify(i);
+      val = "value" + stringify(i);
+      ASSERT_EQ(0, image2.metadata_get(key.c_str(), &value));
+      ASSERT_STREQ(val.c_str(), value.c_str());
+    }
+
+    ASSERT_EQ(0, image.deep_copy_with_progress(ioctx, name3.c_str(), opts, pp));
+    ASSERT_EQ(3, test_ls_pp(rbd, ioctx, 3, name.c_str(), name2.c_str(),
+                            name3.c_str()));
+    ASSERT_EQ(0, rbd.open(ioctx, image3, name3.c_str(), NULL));
+
+    pairs.clear();
+    ASSERT_EQ(0, image3.metadata_list("", 70, &pairs));
+    ASSERT_EQ(70U, pairs.size());
+
+    for (int i = 1; i <= 70; i++) {
+      key = "key" + stringify(i);
+      val = "value" + stringify(i);
+      ASSERT_EQ(0, image3.metadata_get(key.c_str(), &value));
+      ASSERT_STREQ(val.c_str(), value.c_str());
+    }
+  }
+
+  ioctx.close();
+}
+
 int test_ls_snaps(rbd_image_t image, int num_expected, ...)
 {
   int num_snaps, i, j, max_size = 10;
index 5b8d3966131448848a13f1e7bd661ac46d2be18f..676fe21160addd0a13e870675f60951094f40eda 100644 (file)
@@ -1021,6 +1021,36 @@ TRACEPOINT_EVENT(librbd, copy4_exit,
     )
 )
 
+TRACEPOINT_EVENT(librbd, deep_copy_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),
+    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)
+    )
+)
+
+TRACEPOINT_EVENT(librbd, deep_copy_exit,
+    TP_ARGS(
+        int, retval),
+    TP_FIELDS(
+        ctf_integer(int, retval, retval)
+    )
+)
+
 TRACEPOINT_EVENT(librbd, resize_enter,
     TP_ARGS(
         void*, imagectx,