summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>2011-08-31 17:34:06 -0700
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>2011-08-31 17:34:06 -0700
commitd9eacb61048a43c191164f58f8498eeae1411a7f (patch)
tree31f694b91d069b42d97ce7fe997ce7d15603624f
parent9ff3505751059382ad16228d8a02c8db38562a0d (diff)
parent9a26100fc7014e0ba124aa2a7e1d4faf7f7399b6 (diff)
downloadceph-d9eacb61048a43c191164f58f8498eeae1411a7f.tar.gz
Merge branch 'wip-librbd-async-copy'
-rw-r--r--src/include/rbd/librbd.h5
-rw-r--r--src/include/rbd/librbd.hpp9
-rw-r--r--src/librbd.cc98
-rw-r--r--src/testlibrbd.c34
-rw-r--r--src/testlibrbdpp.cc37
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;
}