Skip to content

Commit

Permalink
Merge pull request #19996 from Songweibin/wip-rbd-deep-cp
Browse files Browse the repository at this point in the history
rbd: add deep cp CLI method

Reviewed-by: Jason Dillaman <dillaman@redhat.com>
  • Loading branch information
Jason Dillaman committed Jan 26, 2018
2 parents 19b5648 + 0551029 commit 6253490
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 4 deletions.
4 changes: 4 additions & 0 deletions doc/man/8/rbd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ Commands
Will create a new rbd image. You must also specify the size via --size. The
--stripe-unit and --stripe-count arguments are optional, but must be used together.

:command:`deep cp` (*src-image-spec* | *src-snap-spec*) *dest-image-spec*
Deep copy the content of a src-image into the newly created dest-image.
Dest-image will have the same size, object size, image format, and snapshots as src-image.

:command:`diff` [--from-snap *snap-name*] [--whole-object] *image-spec* | *snap-spec*
Dump a list of byte extents in the image that have changed since the specified start
snapshot, or since the image was created. Each output line includes the starting offset
Expand Down
11 changes: 10 additions & 1 deletion qa/workunits/rbd/cli_generic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# make sure rbd pool is EMPTY.. this is a test script!!
rbd ls | wc -l | grep -v '^0$' && echo "nonempty rbd pool, aborting! run this script on an empty test cluster only." && exit 1

IMGS="testimg1 testimg2 testimg3 testimg-diff1 testimg-diff2 testimg-diff3 foo foo2 bar bar2 test1 test2 test3 clone2"
IMGS="testimg1 testimg2 testimg3 testimg4 testimg5 testimg6 testimg-diff1 testimg-diff2 testimg-diff3 foo foo2 bar bar2 test1 test2 test3 clone2"

tiered=0
if ceph osd dump | grep ^pool | grep "'rbd'" | grep tier; then
Expand Down Expand Up @@ -73,6 +73,14 @@ test_others() {
rbd info testimg-diff2 | grep 'size 256 MB'
rbd info testimg-diff3 | grep 'size 128 MB'

# deep copies
rbd deep copy testimg1 testimg4
rbd deep copy testimg1 --snap=snap1 testimg5
rbd info testimg4 | grep 'size 128 MB'
rbd info testimg5 | grep 'size 256 MB'
rbd snap ls testimg4 | grep -v 'SNAPID' | wc -l | grep 1
rbd snap ls testimg4 | grep '.*snap1.*'

rbd export testimg1 /tmp/img1.new
rbd export testimg2 /tmp/img2.new
rbd export testimg3 /tmp/img3.new
Expand Down Expand Up @@ -100,6 +108,7 @@ test_others() {
rbd rm testimg3
rbd create testimg2 -s 0
rbd cp testimg2 testimg3
rbd deep cp testimg2 testimg6

# remove snapshots
rbd snap rm --snap=snap1 testimg1
Expand Down
24 changes: 24 additions & 0 deletions qa/workunits/rbd/journal.sh
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,30 @@ test_rbd_copy()
rbd remove ${image}
}

test_rbd_deep_copy()
{
local src=testrbdcopys$$
rbd create --size 256 ${src}
rbd snap create ${src}@snap1

local dest=testrbdcopy$$
rbd deep copy --image-feature exclusive-lock --image-feature journaling \
--journal-pool rbd \
--journal-object-size 20M \
--journal-splay-width 6 \
${src} ${dest}

rbd snap purge ${src}
rbd remove ${src}

rbd_assert_eq ${dest} 'journal info' '//journal/order' 25
rbd_assert_eq ${dest} 'journal info' '//journal/splay_width' 6
rbd_assert_eq ${dest} 'journal info' '//journal/object_pool' rbd

rbd snap purge ${dest}
rbd remove ${dest}
}

test_rbd_clone()
{
local parent=testrbdclonep$$
Expand Down
2 changes: 1 addition & 1 deletion src/common/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5905,7 +5905,7 @@ static std::vector<Option> get_rbd_options() {
.set_description("threshold for issuing a sparse-read")
.set_long_description("minimum number of sequential bytes to read against "
"an object before issuing a sparse-read request to "
"the cluster. 0 implies it must be a full object read"
"the cluster. 0 implies it must be a full object read "
"to issue a sparse-read, 1 implies always use "
"sparse-read, and any value larger than the maximum "
"object size will disable sparse-read for all "
Expand Down
2 changes: 1 addition & 1 deletion src/librbd/deep_copy/ObjectCopyRequest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ void ObjectCopyRequest<I>::send_write_object() {
case COPY_OP_TYPE_WRITE:
buffer_offset = 0;
for (auto &e : copy_op.dst_extent_map) {
ldout(m_cct, 20) << ": write op: " << e.first << "~" << e.second
ldout(m_cct, 20) << "write op: " << e.first << "~" << e.second
<< dendl;
bufferlist tmpbl;
tmpbl.substr_of(copy_op.out_bl, buffer_offset, e.second);
Expand Down
4 changes: 3 additions & 1 deletion src/librbd/deep_copy/SnapshotCopyRequest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ void SnapshotCopyRequest<I>::send_snap_unprotect() {
bool src_unprotected;
r = m_src_image_ctx->is_snap_unprotected(snap_seq_it->first,
&src_unprotected);
ldout(m_cct, 20) << "m_src_image_ctx->is_snap_unprotected("<< snap_seq_it->first << "): r=" << r << ", src_unprotected=" << src_unprotected << dendl;
ldout(m_cct, 20) << "m_src_image_ctx->is_snap_unprotected("
<< snap_seq_it->first << "): r=" << r
<< ", src_unprotected=" << src_unprotected << dendl;
if (r == -ENOENT) {
src_unprotected = true;
r = 0;
Expand Down
48 changes: 48 additions & 0 deletions src/test/cli/rbd/help.t
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Skip test on FreeBSD as it generates different output there.
clone Clone a snapshot into a COW child image.
copy (cp) Copy src image to dest.
create Create an empty image.
deep copy (deep cp) Deep copy src image to dest.
diff Print extents that differ since a
previous snap, or image creation.
disk-usage (du) Show disk usage stats for pool, image or
Expand Down Expand Up @@ -304,6 +305,53 @@ Skip test on FreeBSD as it generates different output there.
(-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help deep copy
usage: rbd deep copy [--pool <pool>] [--image <image>] [--snap <snap>]
[--dest-pool <dest-pool>] [--dest <dest>]
[--order <order>] [--object-size <object-size>]
[--image-feature <image-feature>] [--image-shared]
[--stripe-unit <stripe-unit>]
[--stripe-count <stripe-count>] [--data-pool <data-pool>]
[--journal-splay-width <journal-splay-width>]
[--journal-object-size <journal-object-size>]
[--journal-pool <journal-pool>] [--no-progress]
<source-image-or-snap-spec> <dest-image-spec>
Deep copy src image to dest.
Positional arguments
<source-image-or-snap-spec> source image or snapshot specification
(example:
[<pool-name>/]<image-name>[@<snap-name>])
<dest-image-spec> destination image specification
(example: [<pool-name>/]<image-name>)
Optional arguments
-p [ --pool ] arg source pool name
--image arg source image name
--snap arg source snapshot name
--dest-pool arg destination pool name
--dest arg destination image name
--order arg object order [12 <= order <= 25]
--object-size arg object size in B/K/M [4K <= object size <= 32M]
--image-feature arg image features
[layering(+), exclusive-lock(+*),
object-map(+*), fast-diff(+*), deep-flatten(+-),
journaling(*)]
--image-shared shared image
--stripe-unit arg stripe unit in B/K/M
--stripe-count arg stripe count
--data-pool arg data pool
--journal-splay-width arg number of active journal objects
--journal-object-size arg size of journal objects
--journal-pool arg pool for journal objects
--no-progress disable progress output
Image Features:
(*) supports enabling/disabling on existing images
(-) supports disabling-only on existing images
(+) enabled by default for new images if features not specified
rbd help diff
usage: rbd diff [--pool <pool>] [--image <image>] [--snap <snap>]
[--from-snap <from-snap>] [--whole-object] [--format <format>]
Expand Down
6 changes: 6 additions & 0 deletions src/test/cli/rbd/invalid-snap-usage.t
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@
$ rbd cp foo@snap bar@snap
rbd: destination snapname specified for a command that doesn't use it
[22]
$ rbd deep cp foo bar@snap
rbd: destination snapname specified for a command that doesn't use it
[22]
$ rbd deep cp foo@snap bar@snap
rbd: destination snapname specified for a command that doesn't use it
[22]
$ rbd mv foo bar@snap
rbd: destination snapname specified for a command that doesn't use it
[22]
9 changes: 9 additions & 0 deletions src/test/cli/rbd/not-enough-args.t
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
$ rbd cp foo@snap
rbd: destination image name was not specified
[22]
$ rbd deep cp
rbd: image name was not specified
[22]
$ rbd deep cp foo
rbd: destination image name was not specified
[22]
$ rbd deep cp foo@snap
rbd: destination image name was not specified
[22]
$ rbd mv
rbd: image name was not specified
[22]
Expand Down
81 changes: 81 additions & 0 deletions src/tools/rbd/action/Copy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,87 @@ Shell::Action action(
{"copy"}, {"cp"}, "Copy src image to dest.", at::get_long_features_help(),
&get_arguments, &execute);

static int do_deep_copy(librbd::Image &src, librados::IoCtx& dest_pp,
const char *destname, librbd::ImageOptions& opts,
bool no_progress)
{
utils::ProgressContext pc("Image deep copy", no_progress);
int r = src.deep_copy_with_progress(dest_pp, destname, opts, pc);
if (r < 0){
pc.fail();
return r;
}
pc.finish();
return 0;
}

void get_arguments_deep(po::options_description *positional,
po::options_description *options) {
at::add_image_or_snap_spec_options(positional, options,
at::ARGUMENT_MODIFIER_SOURCE);
at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
at::add_create_image_options(options, false);
at::add_no_progress_option(options);
}

int execute_deep(const po::variables_map &vm,
const std::vector<std::string> &ceph_global_init_args) {
size_t arg_index = 0;
std::string pool_name;
std::string image_name;
std::string snap_name;
int r = utils::get_pool_image_snapshot_names(
vm, at::ARGUMENT_MODIFIER_SOURCE, &arg_index, &pool_name, &image_name,
&snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED,
utils::SPEC_VALIDATION_NONE);
if (r < 0) {
return r;
}

std::string dst_pool_name;
std::string dst_image_name;
std::string dst_snap_name;
r = utils::get_pool_image_snapshot_names(
vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dst_pool_name, &dst_image_name,
&dst_snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL);
if (r < 0) {
return r;
}

librbd::ImageOptions opts;
r = utils::get_image_options(vm, false, &opts);
if (r < 0) {
return r;
}

librados::Rados rados;
librados::IoCtx io_ctx;
librbd::Image image;
r = utils::init_and_open_image(pool_name, image_name, "", snap_name, true,
&rados, &io_ctx, &image);
if (r < 0) {
return r;
}

librados::IoCtx dst_io_ctx;
r = utils::init_io_ctx(rados, dst_pool_name, &dst_io_ctx);
if (r < 0) {
return r;
}

r = do_deep_copy(image, dst_io_ctx, dst_image_name.c_str(), opts,
vm[at::NO_PROGRESS].as<bool>());
if (r < 0) {
std::cerr << "rbd: deep copy failed: " << cpp_strerror(r) << std::endl;
return r;
}
return 0;
}

Shell::Action action_deep(
{"deep", "copy"}, {"deep", "cp"}, "Deep copy src image to dest.", at::get_long_features_help(),
&get_arguments_deep, &execute_deep);

} // namespace copy
} // namespace action
} // namespace rbd

0 comments on commit 6253490

Please sign in to comment.