mirror of
https://github.com/ceph/ceph
synced 2025-03-30 15:31:01 +00:00
rados: add whole-object 'clonedata' command
Clone the data stream from one object to another. Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
parent
bd36e78f72
commit
c693ba5732
@ -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
|
||||
|
13
qa/workunits/rados/clone.sh
Executable file
13
qa/workunits/rados/clone.sh
Executable file
@ -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
|
65
src/rados.cc
65
src/rados.cc
@ -72,6 +72,7 @@ void usage(ostream& out)
|
||||
" create <obj-name> [category] create object\n"
|
||||
" rm <obj-name> ... remove object(s)\n"
|
||||
" cp <obj-name> [target-obj] copy object\n"
|
||||
" clonedata <src-obj> <dst-obj> clone object data\n"
|
||||
" listxattr <obj-name>\n"
|
||||
" getxattr <obj-name> attr\n"
|
||||
" setxattr <obj-name> 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<const char *>::iterator iter = nargs.begin();
|
||||
|
Loading…
Reference in New Issue
Block a user