From c693ba57320cdf777f33ad3df7fd5937c69e0cdc Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 6 May 2013 16:45:12 -0700 Subject: [PATCH] rados: add whole-object 'clonedata' command Clone the data stream from one object to another. Signed-off-by: Sage Weil --- doc/man/8/rados.rst | 5 ++- qa/workunits/rados/clone.sh | 13 ++++++++ src/rados.cc | 65 ++++++++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100755 qa/workunits/rados/clone.sh diff --git a/doc/man/8/rados.rst b/doc/man/8/rados.rst index e12f2da646a0..687ea807435e 100644 --- a/doc/man/8/rados.rst +++ b/doc/man/8/rados.rst @@ -87,11 +87,14 @@ Pool specific commands :command:`lssnap` List snapshots for given pool. +:command:`clonedata` *srcname* *dstname* --object-locator *key* + Clone object byte data from *srcname* to *dstname*. Both objects must be stored with the locator key *key* (usually either *srcname* or *dstname*). Object attributes and omap keys are not copied or cloned. + :command:`mksnap` *foo* Create pool snapshot named *foo*. :command:`rmsnap` *foo* - Remove pool snapshot names *foo*. + Remove pool snapshot named *foo*. :command:`bench` *seconds* *mode* [ -b *objsize* ] [ -t *threads* ] Benchmark for seconds. The mode can be write or read. The default diff --git a/qa/workunits/rados/clone.sh b/qa/workunits/rados/clone.sh new file mode 100755 index 000000000000..281e89f71475 --- /dev/null +++ b/qa/workunits/rados/clone.sh @@ -0,0 +1,13 @@ +#!/bin/sh -x + +set -e + +rados -p data rm foo || true +rados -p data put foo.tmp /etc/passwd --object-locator foo +rados -p data clonedata foo.tmp foo --object-locator foo +rados -p data get foo /tmp/foo +cmp /tmp/foo /etc/passwd +rados -p data rm foo.tmp --object-locator foo +rados -p data rm foo + +echo OK \ No newline at end of file diff --git a/src/rados.cc b/src/rados.cc index 9af6a2c823af..8d06d2fa5930 100644 --- a/src/rados.cc +++ b/src/rados.cc @@ -72,6 +72,7 @@ void usage(ostream& out) " create [category] create object\n" " rm ... remove object(s)\n" " cp [target-obj] copy object\n" +" clonedata clone object data\n" " listxattr \n" " getxattr attr\n" " setxattr attr val\n" @@ -301,6 +302,26 @@ err: return ret; } +static int do_clone_data(IoCtx& io_ctx, const char *objname, IoCtx& target_ctx, const char *target_obj) +{ + string oid(objname); + + // get size + uint64_t size; + int r = target_ctx.stat(oid, &size, NULL); + if (r < 0) + return r; + + librados::ObjectWriteOperation write_op; + string target_oid(target_obj); + + /* reset data stream only */ + write_op.create(false); + write_op.truncate(0); + write_op.clone_range(0, oid, 0, size); + return target_ctx.operate(target_oid, &write_op); +} + static int do_copy_pool(Rados& rados, const char *src_pool, const char *target_pool) { IoCtx src_ctx, target_ctx; @@ -1682,7 +1703,49 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, return 1; } } - else if (strcmp(nargs[0], "rm") == 0) { + else if (strcmp(nargs[0], "clonedata") == 0) { + if (!pool_name) + usage_exit(); + + if (nargs.size() < 2 || nargs.size() > 3) + usage_exit(); + + const char *target = target_pool_name; + if (!target) + target = pool_name; + + const char *target_obj; + if (nargs.size() < 3) { + if (strcmp(target, pool_name) == 0) { + cerr << "cannot copy object into itself" << std::endl; + return 1; + } + target_obj = nargs[1]; + } else { + target_obj = nargs[2]; + } + + // open io context. + IoCtx target_ctx; + ret = rados.ioctx_create(target, target_ctx); + if (ret < 0) { + cerr << "error opening target pool " << target << ": " + << strerror_r(-ret, buf, sizeof(buf)) << std::endl; + return 1; + } + if (oloc.size()) { + target_ctx.locator_set_key(oloc); + } else { + cerr << "must specify locator for clone" << std::endl; + return 1; + } + + ret = do_clone_data(io_ctx, nargs[1], target_ctx, target_obj); + if (ret < 0) { + cerr << "error cloning " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << strerror_r(-ret, buf, sizeof(buf)) << std::endl; + return 1; + } + } else if (strcmp(nargs[0], "rm") == 0) { if (!pool_name || nargs.size() < 2) usage_exit(); vector::iterator iter = nargs.begin(); -- 2.47.3