diff options
author | Colin Patrick McCabe <cmccabe@alumni.cmu.edu> | 2011-08-31 17:34:06 -0700 |
---|---|---|
committer | Colin Patrick McCabe <cmccabe@alumni.cmu.edu> | 2011-08-31 17:34:06 -0700 |
commit | d9eacb61048a43c191164f58f8498eeae1411a7f (patch) | |
tree | 31f694b91d069b42d97ce7fe997ce7d15603624f | |
parent | 9ff3505751059382ad16228d8a02c8db38562a0d (diff) | |
parent | 9a26100fc7014e0ba124aa2a7e1d4faf7f7399b6 (diff) | |
download | ceph-d9eacb61048a43c191164f58f8498eeae1411a7f.tar.gz |
Merge branch 'wip-librbd-async-copy'
-rw-r--r-- | src/include/rbd/librbd.h | 5 | ||||
-rw-r--r-- | src/include/rbd/librbd.hpp | 9 | ||||
-rw-r--r-- | src/librbd.cc | 98 | ||||
-rw-r--r-- | src/testlibrbd.c | 34 | ||||
-rw-r--r-- | src/testlibrbdpp.cc | 37 |
5 files changed, 171 insertions, 12 deletions
diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 412e2902608..8389f98972a 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -37,6 +37,9 @@ extern "C" { typedef void *rbd_snap_t; typedef void *rbd_image_t; +typedef int (*librbd_copy_progress_fn_t)(uint64_t offset, uint64_t src_size, + void *data); + typedef struct { uint64_t id; uint64_t size; @@ -69,6 +72,8 @@ int rbd_close(rbd_image_t image); int rbd_resize(rbd_image_t image, uint64_t size); int rbd_stat(rbd_image_t image, rbd_image_info_t *info, size_t infosize); int rbd_copy(rbd_image_t image, rados_ioctx_t dest_io_ctx, const char *destname); +int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p, + const char *destname, librbd_copy_progress_fn_t fn, void *data); /* snapshots */ 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 01ff4f4dc88..956f072576e 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -41,6 +41,13 @@ namespace librbd { typedef rbd_image_info_t image_info_t; +class ProgressContext +{ +public: + virtual ~ProgressContext(); + virtual int update_progress(uint64_t offset, uint64_t src_size) = 0; +}; + class RBD { public: @@ -79,6 +86,8 @@ public: int resize(uint64_t size); int stat(image_info_t &info, size_t infosize); int copy(IoCtx& dest_io_ctx, const char *destname); + int copy_with_progress(IoCtx& dest_io_ctx, const char *destname, + ProgressContext &prog_ctx); /* snapshots */ int snap_list(std::vector<snap_info_t>& snaps); diff --git a/src/librbd.cc b/src/librbd.cc index 2c2ef94384a..3846cb7aeae 100644 --- a/src/librbd.cc +++ b/src/librbd.cc @@ -1012,17 +1012,65 @@ int snap_rollback(ImageCtx *ictx, const char *snap_name) return 0; } -int do_copy_extent(uint64_t offset, size_t len, const char *buf, void *destictx) +struct CopyProgressCtx { + CopyProgressCtx(ProgressContext &p) + : prog_ctx(p) + { + } + ImageCtx *destictx; + uint64_t src_size; + ProgressContext &prog_ctx; +}; + +int do_copy_extent(uint64_t offset, size_t len, const char *buf, void *data) +{ + CopyProgressCtx *cp = reinterpret_cast<CopyProgressCtx*>(data); + if (buf) { + int ret = write(cp->destictx, offset, len, buf); + if (ret) { + return ret; + } + } + return cp->prog_ctx.update_progress(offset, cp->src_size); +} + +ProgressContext::~ProgressContext() { - if (buf) - return write((ImageCtx *)destictx, offset, len, buf); - else - return 0; /* do nothing for holes */ } -int copy(ImageCtx& ictx, IoCtx& dest_md_ctx, const char *destname) +class NoOpProgressContext : public librbd::ProgressContext +{ +public: + NoOpProgressContext() + { + } + int update_progress(uint64_t offset, uint64_t src_size) + { + return 0; + } +}; + +class CProgressContext : public librbd::ProgressContext +{ +public: + CProgressContext(librbd_copy_progress_fn_t fn, void *data) + : m_fn(fn), m_data(data) + { + } + int update_progress(uint64_t offset, uint64_t src_size) + { + return m_fn(offset, src_size, m_data); + } +private: + librbd_copy_progress_fn_t m_fn; + void *m_data; +}; + +int copy(ImageCtx& ictx, IoCtx& dest_md_ctx, const char *destname, + ProgressContext &prog_ctx) { CephContext *cct = dest_md_ctx.cct(); + CopyProgressCtx cp(prog_ctx); uint64_t src_size = ictx.get_image_size(); @@ -1033,15 +1081,20 @@ int copy(ImageCtx& ictx, IoCtx& dest_md_ctx, const char *destname) return r; } - ImageCtx *destictx = new librbd::ImageCtx(destname, dest_md_ctx); - r = open_image(dest_md_ctx, destictx, destname, NULL); + cp.destictx = new librbd::ImageCtx(destname, dest_md_ctx); + cp.src_size = src_size; + r = open_image(dest_md_ctx, cp.destictx, destname, NULL); if (r < 0) { lderr(cct) << "failed to read newly created header" << dendl; return r; } - r = read_iterate(&ictx, 0, src_size, do_copy_extent, destictx); - close_image(destictx); + r = read_iterate(&ictx, 0, src_size, do_copy_extent, &cp); + + if (r >= 0) { + prog_ctx.update_progress(cp.src_size, cp.src_size); + } + close_image(cp.destictx); return r; } @@ -1556,7 +1609,16 @@ int Image::stat(image_info_t& info, size_t infosize) int Image::copy(IoCtx& dest_io_ctx, const char *destname) { ImageCtx *ictx = (ImageCtx *)ctx; - int r = librbd::copy(*ictx, dest_io_ctx, destname); + librbd::NoOpProgressContext prog_ctx; + int r = librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx); + return r; +} + +int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname, + librbd::ProgressContext &pctx) +{ + ImageCtx *ictx = (ImageCtx *)ctx; + int r = librbd::copy(*ictx, dest_io_ctx, destname, pctx); return r; } @@ -1694,7 +1756,19 @@ extern "C" int rbd_copy(rbd_image_t image, rados_ioctx_t dest_p, const char *des librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; librados::IoCtx dest_io_ctx; librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx); - return librbd::copy(*ictx, dest_io_ctx, destname); + librbd::NoOpProgressContext prog_ctx; + return librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx); +} + +extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p, + const char *destname, librbd_copy_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); + librbd::CProgressContext prog_ctx(fn, data); + int ret = librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx); + return ret; } extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname, const char *destname) diff --git a/src/testlibrbd.c b/src/testlibrbd.c index eddffd8946b..5624ebb5d9f 100644 --- a/src/testlibrbd.c +++ b/src/testlibrbd.c @@ -26,6 +26,7 @@ #include <unistd.h> #define TEST_IMAGE "testimg" +#define TEST_IMAGE2 "testimg2" #define TEST_POOL "librbdtest" #define TEST_SNAP "testsnap" #define TEST_IO_SIZE 512 @@ -325,6 +326,35 @@ void test_io_to_snapshot(rados_ioctx_t io_ctx, rbd_image_t image, size_t isize) test_ls_snaps(image, 0); } +void test_rbd_copy(rados_ioctx_t io_ctx, rbd_image_t image) +{ + int ret; + ret = rbd_copy(image, io_ctx, TEST_IMAGE2); + if (ret < 0) { + fprintf(stderr, "rbd_copy returned %d!\n", ret); + abort(); + } +} + +static int print_progress_percent(uint64_t offset, uint64_t src_size, + void *data) +{ + float percent = ((float)offset * 100) / src_size; + printf("%3.2f%% done\n", percent); + return 0; +} + +void test_rbd_copy_with_progress(rados_ioctx_t io_ctx, rbd_image_t image) +{ + int ret; + ret = rbd_copy_with_progress(image, io_ctx, TEST_IMAGE2, + print_progress_percent, NULL); + if (ret < 0) { + fprintf(stderr, "rbd_copy_with_progress returned %d!\n", ret); + abort(); + } +} + int main(int argc, const char **argv) { rados_t cluster; @@ -380,6 +410,10 @@ int main(int argc, const char **argv) test_delete(io_ctx, TEST_IMAGE "1"); test_ls(io_ctx, 0); + test_rbd_copy(io_ctx, image); + test_delete(io_ctx, TEST_IMAGE2); + test_rbd_copy_with_progress(io_ctx, image); + rados_ioctx_destroy(io_ctx); rados_shutdown(cluster); diff --git a/src/testlibrbdpp.cc b/src/testlibrbdpp.cc index 4a6de01265e..319ff52b93e 100644 --- a/src/testlibrbdpp.cc +++ b/src/testlibrbdpp.cc @@ -31,6 +31,7 @@ using namespace std; #define TEST_IMAGE "testimg" +#define TEST_IMAGE2 "testimg2" #define TEST_POOL "librbdtest" #define TEST_SNAP "testsnap" #define TEST_IO_SIZE 513 @@ -237,6 +238,39 @@ void test_io(librados::IoCtx& io_ctx, librbd::Image& image) } +void test_rbd_copy(librados::IoCtx& io_ctx, librbd::Image& image) +{ + int ret; + ret = image.copy(io_ctx, TEST_IMAGE2); + if (ret < 0) { + fprintf(stderr, "image.copy returned %d!\n", ret); + abort(); + } +} + +class PrintProgress : public librbd::ProgressContext +{ +public: + int update_progress(uint64_t offset, uint64_t src_size) + { + float percent = ((float)offset * 100) / src_size; + printf("%3.2f%% done\n", percent); + return 0; + } +}; + + +void test_rbd_copy_with_progress(librados::IoCtx& io_ctx, librbd::Image& image) +{ + int ret; + PrintProgress prog_ctx; + ret = image.copy_with_progress(io_ctx, TEST_IMAGE2, prog_ctx); + if (ret < 0) { + fprintf(stderr, "image.copy returned %d!\n", ret); + abort(); + } +} + int main(int argc, const char **argv) { librados::Rados rados; @@ -275,6 +309,9 @@ int main(int argc, const char **argv) test_ls(io_ctx, 1, TEST_IMAGE "1"); test_delete(io_ctx, TEST_IMAGE "1"); test_ls(io_ctx, 0); + test_rbd_copy(io_ctx, image); + test_delete(io_ctx, TEST_IMAGE2); + test_rbd_copy_with_progress(io_ctx, image); delete rbd; return 0; } |