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
# 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
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
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
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$$
.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 "
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);
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;
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
(-) 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>]
$ 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]
$ 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]
{"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