From: Mykola Golub Date: Tue, 31 Oct 2017 20:56:07 +0000 (+0200) Subject: librbd: add deep_copy function to API X-Git-Tag: v13.0.1~279^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=97db2b2a4ce156ea32f92f5d6a91a180a35fab62;p=ceph.git librbd: add deep_copy function to API Signed-off-by: Mykola Golub --- diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index a7f09b10afad..23c166a58f5b 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -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); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index bbf4270bc245..7e9825d2d45c 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -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; diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index c71aa7697c44..ddb6ef17769a 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -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) { diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 514b8b3fb8aa..36b32b5587e8 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -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 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; diff --git a/src/tracing/librbd.tp b/src/tracing/librbd.tp index 5b8d39661314..676fe21160ad 100644 --- a/src/tracing/librbd.tp +++ b/src/tracing/librbd.tp @@ -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,