From 5622d3ff7d9383ca244229e1b8f9f1b63f82665d Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Tue, 17 Nov 2015 09:56:17 +0200 Subject: [PATCH] rbd: alow to specify options for created journal Signed-off-by: Mykola Golub --- qa/workunits/rbd/journal.sh | 119 ++++++++++++++++++++++ src/test/cli/rbd/help.t | 168 ++++++++++++++++++++------------ src/tools/rbd/ArgumentTypes.cc | 26 +++++ src/tools/rbd/ArgumentTypes.h | 11 +++ src/tools/rbd/Utils.cc | 109 +++++++++++++++------ src/tools/rbd/Utils.h | 6 +- src/tools/rbd/action/Clone.cc | 21 ++-- src/tools/rbd/action/Copy.cc | 17 +++- src/tools/rbd/action/Create.cc | 29 +++--- src/tools/rbd/action/Feature.cc | 27 ++++- src/tools/rbd/action/Import.cc | 47 ++++----- 11 files changed, 431 insertions(+), 149 deletions(-) diff --git a/qa/workunits/rbd/journal.sh b/qa/workunits/rbd/journal.sh index 99c647b3ddaf4..022a882482630 100755 --- a/qa/workunits/rbd/journal.sh +++ b/qa/workunits/rbd/journal.sh @@ -99,7 +99,126 @@ test_rbd_journal() rbd remove ${image} } + +rbd_assert_eq() { + local image=$1 + local cmd=$2 + local param=$3 + local expected_val=$4 + + local val=$(rbd --format xml ${cmd} --image ${image} | + $XMLSTARLET sel -t -v "${param}") + test "${val}" = "${expected_val}" +} + +test_rbd_create() +{ + local image=testrbdcreate$$ + + rbd create --image-feature exclusive-lock --image-feature journaling \ + --journal-pool rbd \ + --journal-object-size 20M \ + --journal-splay-width 6 \ + --size 256 ${image} + + rbd_assert_eq ${image} 'journal info' '//journal/order' 25 + rbd_assert_eq ${image} 'journal info' '//journal/splay_width' 6 + rbd_assert_eq ${image} 'journal info' '//journal/object_pool' rbd + + rbd remove ${image} +} + +test_rbd_copy() +{ + local src=testrbdcopys$$ + rbd create --size 256 ${src} + + local image=testrbdcopy$$ + rbd copy --image-feature exclusive-lock --image-feature journaling \ + --journal-pool rbd \ + --journal-object-size 20M \ + --journal-splay-width 6 \ + ${src} ${image} + + rbd remove ${src} + + rbd_assert_eq ${image} 'journal info' '//journal/order' 25 + rbd_assert_eq ${image} 'journal info' '//journal/splay_width' 6 + rbd_assert_eq ${image} 'journal info' '//journal/object_pool' rbd + + rbd remove ${image} +} + +test_rbd_clone() +{ + local parent=testrbdclonep$$ + rbd create --image-feature layering --size 256 ${parent} + rbd snap create ${parent}@snap + rbd snap protect ${parent}@snap + + local image=testrbdclone$$ + rbd clone --image-feature layering --image-feature exclusive-lock --image-feature journaling \ + --journal-pool rbd \ + --journal-object-size 20M \ + --journal-splay-width 6 \ + ${parent}@snap ${image} + + rbd_assert_eq ${image} 'journal info' '//journal/order' 25 + rbd_assert_eq ${image} 'journal info' '//journal/splay_width' 6 + rbd_assert_eq ${image} 'journal info' '//journal/object_pool' rbd + + rbd remove ${image} + rbd snap unprotect ${parent}@snap + rbd snap purge ${parent} + rbd remove ${parent} +} + +test_rbd_import() +{ + local src=testrbdimports$$ + rbd create --size 256 ${src} + + rbd export ${src} $TMPDIR/${src}.export + rbd remove ${src} + + local image=testrbdimport$$ + rbd import --image-feature exclusive-lock --image-feature journaling \ + --journal-pool rbd \ + --journal-object-size 20M \ + --journal-splay-width 6 \ + $TMPDIR/${src}.export ${image} + + rbd_assert_eq ${image} 'journal info' '//journal/order' 25 + rbd_assert_eq ${image} 'journal info' '//journal/splay_width' 6 + rbd_assert_eq ${image} 'journal info' '//journal/object_pool' rbd + + rbd remove ${image} +} + +test_rbd_feature() +{ + local image=testrbdfeature$$ + + rbd create --image-feature exclusive-lock --size 256 ${image} + + rbd feature enable ${image} journaling \ + --journal-pool rbd \ + --journal-object-size 20M \ + --journal-splay-width 6 + + rbd_assert_eq ${image} 'journal info' '//journal/order' 25 + rbd_assert_eq ${image} 'journal info' '//journal/splay_width' 6 + rbd_assert_eq ${image} 'journal info' '//journal/object_pool' rbd + + rbd remove ${image} +} + TESTS+=" rbd_journal" +TESTS+=" rbd_create" +TESTS+=" rbd_copy" +TESTS+=" rbd_clone" +TESTS+=" rbd_import" +TESTS+=" rbd_feature" # # "main" follows diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index b459056ca7aaa..8e4a36c5b5e6b 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -125,29 +125,37 @@ [--dest-pool ] [--dest ] [--order ] [--image-feature ] [--image-shared] [--stripe-unit ] [--stripe-count ] + [--journal-splay-width ] + [--journal-object-size ] + [--journal-pool ] Clone a snapshot into a COW child image. Positional arguments - source snapshot specification - (example: [/]@) - destination image specification - (example: [/]) + source snapshot specification + (example: + [/]@) + destination image specification + (example: [/]) 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] - --image-feature arg image features - [layering(+), striping(+), exclusive-lock(*), - object-map(*), fast-diff(*), deep-flatten, journaling(*)] - --image-shared shared image - --stripe-unit arg stripe unit - --stripe-count arg stripe count + -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] + --image-feature arg image features + [layering(+), striping(+), exclusive-lock(*), + object-map(*), fast-diff(*), deep-flatten, + journaling(*)] + --image-shared shared image + --stripe-unit arg stripe unit + --stripe-count arg stripe count + --journal-splay-width arg number of active journal objects + --journal-object-size arg size of journal objects + --journal-pool arg pool for journal objects Image Features: (*) supports enabling/disabling on existing images @@ -155,7 +163,12 @@ rbd help copy usage: rbd copy [--pool ] [--image ] [--snap ] - [--dest-pool ] [--dest ] [--no-progress] + [--dest-pool ] [--dest ] [--order ] + [--image-feature ] [--image-shared] + [--stripe-unit ] [--stripe-count ] + [--journal-splay-width ] + [--journal-object-size ] + [--journal-pool ] [--no-progress] Copy src image to dest. @@ -173,36 +186,58 @@ --snap arg source snapshot name --dest-pool arg destination pool name --dest arg destination image name + --order arg object order [12 <= order <= 25] + --image-feature arg image features + [layering(+), striping(+), exclusive-lock(*), + object-map(*), fast-diff(*), deep-flatten, + journaling(*)] + --image-shared shared image + --stripe-unit arg stripe unit + --stripe-count arg stripe count + --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 + (+) enabled by default for new images if features not specified + rbd help create usage: rbd create [--pool ] [--image ] [--image-format ] [--new-format] [--order ] [--image-feature ] [--image-shared] [--stripe-unit ] - [--stripe-count ] --size + [--stripe-count ] + [--journal-splay-width ] + [--journal-object-size ] + [--journal-pool ] --size Create an empty image. Positional arguments - image specification - (example: [/]) + image specification + (example: [/]) Optional arguments - -p [ --pool ] arg pool name - --image arg image name - --image-format arg image format [1 or 2] - --new-format use image format 2 - (deprecated) - --order arg object order [12 <= order <= 25] - --image-feature arg image features - [layering(+), striping(+), exclusive-lock(*), - object-map(*), fast-diff(*), deep-flatten, journaling(*)] - --image-shared shared image - --stripe-unit arg stripe unit - --stripe-count arg stripe count - -s [ --size ] arg image size (in M/G/T) + -p [ --pool ] arg pool name + --image arg image name + --image-format arg image format [1 or 2] + --new-format use image format 2 + (deprecated) + --order arg object order [12 <= order <= 25] + --image-feature arg image features + [layering(+), striping(+), exclusive-lock(*), + object-map(*), fast-diff(*), deep-flatten, + journaling(*)] + --image-shared shared image + --stripe-unit arg stripe unit + --stripe-count arg stripe count + --journal-splay-width arg number of active journal objects + --journal-object-size arg size of journal objects + --journal-pool arg pool for journal objects + -s [ --size ] arg image size (in M/G/T) Image Features: (*) supports enabling/disabling on existing images @@ -309,20 +344,26 @@ rbd help feature enable usage: rbd feature enable [--pool ] [--image ] + [--journal-splay-width ] + [--journal-object-size ] + [--journal-pool ] [ ...] Enable the specified image feature. Positional arguments - image specification - (example: [/]) - image features - [layering, striping, exclusive-lock, object-map, - fast-diff, deep-flatten, journaling] + image specification + (example: [/]) + image features + [layering, striping, exclusive-lock, object-map, + fast-diff, deep-flatten, journaling] Optional arguments - -p [ --pool ] arg pool name - --image arg image name + -p [ --pool ] arg pool name + --image arg image name + --journal-splay-width arg number of active journal objects + --journal-object-size arg size of journal objects + --journal-pool arg pool for journal objects rbd help flatten usage: rbd flatten [--pool ] [--image ] [--no-progress] @@ -407,34 +448,41 @@ [--image-format ] [--new-format] [--order ] [--image-feature ] [--image-shared] [--stripe-unit ] - [--stripe-count ] [--no-progress] + [--stripe-count ] + [--journal-splay-width ] + [--journal-object-size ] + [--journal-pool ] [--no-progress] [--pool ] [--image ] Import image from file. Positional arguments - import file (or '-' for stdin) - destination image specification - (example: [/]) + import file (or '-' for stdin) + destination image specification + (example: [/]) Optional arguments - --path arg import file (or '-' for stdin) - --dest-pool arg destination pool name - --dest arg destination image name - --image-format arg image format [1 or 2] - --new-format use image format 2 - (deprecated) - --order arg object order [12 <= order <= 25] - --image-feature arg image features - [layering(+), striping(+), exclusive-lock(*), - object-map(*), fast-diff(*), deep-flatten, journaling(*)] - --image-shared shared image - --stripe-unit arg stripe unit - --stripe-count arg stripe count - --no-progress disable progress output - -p [ --pool ] arg pool name (deprecated) - --image arg image name (deprecated) + --path arg import file (or '-' for stdin) + --dest-pool arg destination pool name + --dest arg destination image name + --image-format arg image format [1 or 2] + --new-format use image format 2 + (deprecated) + --order arg object order [12 <= order <= 25] + --image-feature arg image features + [layering(+), striping(+), exclusive-lock(*), + object-map(*), fast-diff(*), deep-flatten, + journaling(*)] + --image-shared shared image + --stripe-unit arg stripe unit + --stripe-count arg stripe count + --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 + -p [ --pool ] arg pool name (deprecated) + --image arg image name (deprecated) Image Features: (*) supports enabling/disabling on existing images diff --git a/src/tools/rbd/ArgumentTypes.cc b/src/tools/rbd/ArgumentTypes.cc index 0c3dc5597f87e..43bb80b0acdf8 100644 --- a/src/tools/rbd/ArgumentTypes.cc +++ b/src/tools/rbd/ArgumentTypes.cc @@ -223,6 +223,18 @@ void add_create_image_options(po::options_description *opt, (IMAGE_SHARED.c_str(), po::bool_switch(), "shared image") (IMAGE_STRIPE_UNIT.c_str(), po::value(), "stripe unit") (IMAGE_STRIPE_COUNT.c_str(), po::value(), "stripe count"); + + add_create_journal_options(opt); +} + +void add_create_journal_options(po::options_description *opt) { + opt->add_options() + (JOURNAL_SPLAY_WIDTH.c_str(), po::value(), + "number of active journal objects") + (JOURNAL_OBJECT_SIZE.c_str(), po::value(), + "size of journal objects") + (JOURNAL_POOL.c_str(), po::value(), + "pool for journal objects"); } void add_size_option(boost::program_options::options_description *opt) { @@ -393,5 +405,19 @@ void validate(boost::any& v, const std::vector& values, } } +void validate(boost::any& v, const std::vector& values, + JournalObjectSize *target_type, int) { + po::validators::check_first_occurrence(v); + const std::string &s = po::validators::get_single_string(values); + + std::string parse_error; + uint64_t size = strict_sistrtoll(s.c_str(), &parse_error); + if (parse_error.empty() && (size >= (1 << 12))) { + v = boost::any(size); + return; + } + throw po::validation_error(po::validation_error::invalid_option_value); +} + } // namespace argument_types } // namespace rbd diff --git a/src/tools/rbd/ArgumentTypes.h b/src/tools/rbd/ArgumentTypes.h index e9240f27cb945..56ae1a1510a03 100644 --- a/src/tools/rbd/ArgumentTypes.h +++ b/src/tools/rbd/ArgumentTypes.h @@ -65,6 +65,10 @@ static const std::string IMAGE_SIZE("size"); static const std::string IMAGE_STRIPE_UNIT("stripe-unit"); static const std::string IMAGE_STRIPE_COUNT("stripe-count"); +static const std::string JOURNAL_OBJECT_SIZE("journal-object-size"); +static const std::string JOURNAL_SPLAY_WIDTH("journal-splay-width"); +static const std::string JOURNAL_POOL("journal-pool"); + static const std::string NO_PROGRESS("no-progress"); static const std::string FORMAT("format"); static const std::string PRETTY_FORMAT("pretty-format"); @@ -99,6 +103,8 @@ struct Format : public TypedValue { Formatter create_formatter(bool pretty) const; }; +struct JournalObjectSize {}; + std::string get_name_prefix(ArgumentModifier modifier); std::string get_description_prefix(ArgumentModifier modifier); @@ -141,6 +147,9 @@ void add_journal_spec_options( void add_create_image_options(boost::program_options::options_description *opt, bool include_format); +void add_create_journal_options( + boost::program_options::options_description *opt); + void add_size_option(boost::program_options::options_description *opt); void add_path_options(boost::program_options::options_description *pos, @@ -170,6 +179,8 @@ void validate(boost::any& v, const std::vector& values, ImageFeatures *target_type, int); void validate(boost::any& v, const std::vector& values, Format *target_type, int); +void validate(boost::any& v, const std::vector& values, + JournalObjectSize *target_type, int); std::ostream &operator<<(std::ostream &os, const ImageFeatures &features); diff --git a/src/tools/rbd/Utils.cc b/src/tools/rbd/Utils.cc index cb71ebdf1e24c..00d0e79ba1b2d 100644 --- a/src/tools/rbd/Utils.cc +++ b/src/tools/rbd/Utils.cc @@ -316,89 +316,138 @@ int validate_snapshot_name(at::ArgumentModifier mod, } int get_image_options(const boost::program_options::variables_map &vm, - int *order, uint32_t *format, uint64_t *features, - uint32_t *stripe_unit, uint32_t *stripe_count) { + bool get_format, librbd::ImageOptions *opts) { + uint64_t order, features, stripe_unit, stripe_count; + bool features_specified = false; + if (vm.count(at::IMAGE_ORDER)) { - *order = vm[at::IMAGE_ORDER].as(); + order = vm[at::IMAGE_ORDER].as(); } else { - *order = 22; + order = 22; } - bool features_specified = false; if (vm.count(at::IMAGE_FEATURES)) { - *features = vm[at::IMAGE_FEATURES].as(); + features = vm[at::IMAGE_FEATURES].as(); features_specified = true; } else { - *features = g_conf->rbd_default_features; + features = g_conf->rbd_default_features; } if (vm.count(at::IMAGE_STRIPE_UNIT)) { - *stripe_unit = vm[at::IMAGE_STRIPE_UNIT].as(); + stripe_unit = vm[at::IMAGE_STRIPE_UNIT].as(); } else { - *stripe_unit = g_conf->rbd_default_stripe_unit; + stripe_unit = g_conf->rbd_default_stripe_unit; } if (vm.count(at::IMAGE_STRIPE_COUNT)) { - *stripe_count = vm[at::IMAGE_STRIPE_COUNT].as(); + stripe_count = vm[at::IMAGE_STRIPE_COUNT].as(); } else { - *stripe_count = g_conf->rbd_default_stripe_count; + stripe_count = g_conf->rbd_default_stripe_count; } - if ((*stripe_unit != 0 && *stripe_count == 0) || - (*stripe_unit == 0 && *stripe_count != 0)) { + if ((stripe_unit != 0 && stripe_count == 0) || + (stripe_unit == 0 && stripe_count != 0)) { std::cerr << "must specify both (or neither) of stripe-unit and stripe-count" << std::endl; return -EINVAL; - } else if ((*stripe_unit || *stripe_count) && - (*stripe_unit != (1ll << *order) && *stripe_count != 1)) { - *features |= RBD_FEATURE_STRIPINGV2; + } else if ((stripe_unit || stripe_count) && + (stripe_unit != (1ull << order) && stripe_count != 1)) { + features |= RBD_FEATURE_STRIPINGV2; } else { - *features &= ~RBD_FEATURE_STRIPINGV2; + features &= ~RBD_FEATURE_STRIPINGV2; } if (vm.count(at::IMAGE_SHARED) && vm[at::IMAGE_SHARED].as()) { - *features &= ~RBD_FEATURES_SINGLE_CLIENT; + features &= ~RBD_FEATURES_SINGLE_CLIENT; } - if (format != nullptr) { + if (get_format) { + uint64_t format; bool format_specified = false; if (vm.count(at::IMAGE_NEW_FORMAT)) { - *format = 2; + format = 2; format_specified = true; } else if (vm.count(at::IMAGE_FORMAT)) { - *format = vm[at::IMAGE_FORMAT].as(); + format = vm[at::IMAGE_FORMAT].as(); format_specified = true; } else { - *format = g_conf->rbd_default_format; + format = g_conf->rbd_default_format; } - if (features_specified && *features != 0) { - if (format_specified && *format == 1) { + if (features_specified && features != 0) { + if (format_specified && format == 1) { std::cerr << "rbd: features not allowed with format 1; " << "use --image-format 2" << std::endl; return -EINVAL; } else { - *format = 2; + format = 2; format_specified = true; } } - if ((*stripe_unit || *stripe_count) && - (*stripe_unit != (1ull << *order) && *stripe_count != 1)) { - if (format_specified && *format == 1) { + if ((stripe_unit || stripe_count) && + (stripe_unit != (1ull << order) && stripe_count != 1)) { + if (format_specified && format == 1) { std::cerr << "rbd: non-default striping not allowed with format 1; " << "use --image-format 2" << std::endl; return -EINVAL; } else { - *format = 2; + format = 2; format_specified = 2; } } if (format_specified) { - int r = g_conf->set_val("rbd_default_format", stringify(*format)); + int r = g_conf->set_val("rbd_default_format", stringify(format)); assert(r == 0); } + + opts->set(RBD_IMAGE_OPTION_FORMAT, format); + } + + opts->set(RBD_IMAGE_OPTION_ORDER, order); + opts->set(RBD_IMAGE_OPTION_FEATURES, features); + opts->set(RBD_IMAGE_OPTION_STRIPE_UNIT, stripe_unit); + opts->set(RBD_IMAGE_OPTION_STRIPE_COUNT, stripe_count); + + int r = get_journal_options(vm, opts); + if (r < 0) { + return r; + } + + return 0; +} + +int get_journal_options(const boost::program_options::variables_map &vm, + librbd::ImageOptions *opts) { + + if (vm.count(at::JOURNAL_OBJECT_SIZE)) { + uint64_t size = vm[at::JOURNAL_OBJECT_SIZE].as(); + uint64_t order = 12; + while ((1ULL << order) < size) { + order++; + } + opts->set(RBD_IMAGE_OPTION_JOURNAL_ORDER, order); + + int r = g_conf->set_val("rbd_journal_order", stringify(order)); + assert(r == 0); + } + if (vm.count(at::JOURNAL_SPLAY_WIDTH)) { + opts->set(RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH, + vm[at::JOURNAL_SPLAY_WIDTH].as()); + + int r = g_conf->set_val("rbd_journal_splay_width", + stringify( + vm[at::JOURNAL_SPLAY_WIDTH].as())); + assert(r == 0); + } + if (vm.count(at::JOURNAL_POOL)) { + opts->set(RBD_IMAGE_OPTION_JOURNAL_POOL, + vm[at::JOURNAL_POOL].as()); + + int r = g_conf->set_val("rbd_journal_pool", + vm[at::JOURNAL_POOL].as()); + assert(r == 0); } return 0; diff --git a/src/tools/rbd/Utils.h b/src/tools/rbd/Utils.h index 1e4ef6c001e38..0f290df237db1 100644 --- a/src/tools/rbd/Utils.h +++ b/src/tools/rbd/Utils.h @@ -65,8 +65,10 @@ int validate_snapshot_name(argument_types::ArgumentModifier mod, SnapshotPresence snapshot_presence); int get_image_options(const boost::program_options::variables_map &vm, - int *order, uint32_t *format, uint64_t *features, - uint32_t *stripe_unit, uint32_t *stripe_count); + bool get_format, librbd::ImageOptions* opts); + +int get_journal_options(const boost::program_options::variables_map &vm, + librbd::ImageOptions *opts); int get_image_size(const boost::program_options::variables_map &vm, uint64_t *size); diff --git a/src/tools/rbd/action/Clone.cc b/src/tools/rbd/action/Clone.cc index 6c98433d7430a..df24349befc03 100644 --- a/src/tools/rbd/action/Clone.cc +++ b/src/tools/rbd/action/Clone.cc @@ -18,14 +18,16 @@ namespace po = boost::program_options; int do_clone(librbd::RBD &rbd, librados::IoCtx &p_ioctx, const char *p_name, const char *p_snapname, librados::IoCtx &c_ioctx, const char *c_name, - uint64_t features, int *c_order, - uint64_t stripe_unit, uint64_t stripe_count) { + librbd::ImageOptions& opts) { + uint64_t features; + int r = opts.get(RBD_IMAGE_OPTION_FEATURES, &features); + assert(r == 0); + if ((features & RBD_FEATURE_LAYERING) != RBD_FEATURE_LAYERING) { return -EINVAL; } - return rbd.clone2(p_ioctx, p_name, p_snapname, c_ioctx, c_name, features, - c_order, stripe_unit, stripe_count); + return rbd.clone3(p_ioctx, p_name, p_snapname, c_ioctx, c_name, opts); } void get_arguments(po::options_description *positional, @@ -57,12 +59,8 @@ int execute(const po::variables_map &vm) { return r; } - int order; - uint64_t features; - uint32_t stripe_unit; - uint32_t stripe_count; - r = utils::get_image_options(vm, &order, nullptr, &features, &stripe_unit, - &stripe_count); + librbd::ImageOptions opts; + r = utils::get_image_options(vm, false, &opts); if (r < 0) { return r; } @@ -82,8 +80,7 @@ int execute(const po::variables_map &vm) { librbd::RBD rbd; r = do_clone(rbd, io_ctx, image_name.c_str(), snap_name.c_str(), dst_io_ctx, - dst_image_name.c_str(), features, &order, stripe_unit, - stripe_count); + dst_image_name.c_str(), opts); if (r < 0) { std::cerr << "rbd: clone error: " << cpp_strerror(r) << std::endl; return r; diff --git a/src/tools/rbd/action/Copy.cc b/src/tools/rbd/action/Copy.cc index 9275e4b33f1e1..7ab53aeb62129 100644 --- a/src/tools/rbd/action/Copy.cc +++ b/src/tools/rbd/action/Copy.cc @@ -16,10 +16,11 @@ namespace at = argument_types; namespace po = boost::program_options; static int do_copy(librbd::Image &src, librados::IoCtx& dest_pp, - const char *destname, bool no_progress) + const char *destname, librbd::ImageOptions& opts, + bool no_progress) { utils::ProgressContext pc("Image copy", no_progress); - int r = src.copy_with_progress(dest_pp, destname, pc); + int r = src.copy_with_progress3(dest_pp, destname, opts, pc); if (r < 0){ pc.fail(); return r; @@ -33,6 +34,7 @@ void get_arguments(po::options_description *positional, 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); } @@ -58,6 +60,12 @@ int execute(const po::variables_map &vm) { 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; @@ -73,7 +81,7 @@ int execute(const po::variables_map &vm) { return r; } - r = do_copy(image, dst_io_ctx, dst_image_name.c_str(), + r = do_copy(image, dst_io_ctx, dst_image_name.c_str(), opts, vm[at::NO_PROGRESS].as()); if (r < 0) { std::cerr << "rbd: copy failed: " << cpp_strerror(r) << std::endl; @@ -83,7 +91,8 @@ int execute(const po::variables_map &vm) { } Shell::Action action( - {"copy"}, {"cp"}, "Copy src image to dest.", "", &get_arguments, &execute); + {"copy"}, {"cp"}, "Copy src image to dest.", at::get_long_features_help(), + &get_arguments, &execute); } // namespace copy } // namespace action diff --git a/src/tools/rbd/action/Create.cc b/src/tools/rbd/action/Create.cc index 49eedb6cc2a0d..58919392e365a 100644 --- a/src/tools/rbd/action/Create.cc +++ b/src/tools/rbd/action/Create.cc @@ -16,15 +16,20 @@ namespace at = argument_types; namespace po = boost::program_options; static int do_create(librbd::RBD &rbd, librados::IoCtx& io_ctx, - const char *imgname, uint64_t size, int *order, - int format, uint64_t features, - uint64_t stripe_unit, uint64_t stripe_count) { + const char *imgname, uint64_t size, + librbd::ImageOptions& opts) { int r; + uint64_t format; + r = opts.get(RBD_IMAGE_OPTION_FORMAT, &format); + assert(r == 0); if (format == 1) { - r = rbd.create(io_ctx, imgname, size, order); + uint64_t order; + r = opts.get(RBD_IMAGE_OPTION_ORDER, &order); + assert(r == 0); + int order_ = order; + r = rbd.create(io_ctx, imgname, size, &order_); } else { - r = rbd.create3(io_ctx, imgname, size, features, order, - stripe_unit, stripe_count); + r = rbd.create4(io_ctx, imgname, size, opts); } if (r < 0) { return r; @@ -51,13 +56,8 @@ int execute(const po::variables_map &vm) { return r; } - int order; - uint32_t format; - uint64_t features; - uint32_t stripe_unit; - uint32_t stripe_count; - r = utils::get_image_options(vm, &order, &format, &features, &stripe_unit, - &stripe_count); + librbd::ImageOptions opts; + r = utils::get_image_options(vm, true, &opts); if (r < 0) { return r; } @@ -76,8 +76,7 @@ int execute(const po::variables_map &vm) { } librbd::RBD rbd; - r = do_create(rbd, io_ctx, image_name.c_str(), size, &order, format, features, - stripe_unit, stripe_count); + r = do_create(rbd, io_ctx, image_name.c_str(), size, opts); if (r < 0) { std::cerr << "rbd: create error: " << cpp_strerror(r) << std::endl; return r; diff --git a/src/tools/rbd/action/Feature.cc b/src/tools/rbd/action/Feature.cc index 4bd61a6aa9a81..12d4dd8cf8cb3 100644 --- a/src/tools/rbd/action/Feature.cc +++ b/src/tools/rbd/action/Feature.cc @@ -4,8 +4,10 @@ #include "tools/rbd/ArgumentTypes.h" #include "tools/rbd/Shell.h" #include "tools/rbd/Utils.h" +#include "include/stringify.h" #include "common/errno.h" #include +#include #include namespace rbd { @@ -16,11 +18,24 @@ namespace at = argument_types; namespace po = boost::program_options; void get_arguments(po::options_description *positional, - po::options_description *options) { + po::options_description *options, bool enabled) { at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); positional->add_options() ("features", po::value()->multitoken(), ("image features\n" + at::get_short_features_help(false)).c_str()); + if (enabled) { + at::add_create_journal_options(options); + } +} + +void get_arguments_disable(po::options_description *positional, + po::options_description *options) { + get_arguments(positional, options, false); +} + +void get_arguments_enable(po::options_description *positional, + po::options_description *options) { + get_arguments(positional, options, true); } int execute(const po::variables_map &vm, bool enabled) { @@ -35,6 +50,12 @@ int execute(const po::variables_map &vm, bool enabled) { return r; } + librbd::ImageOptions opts; + r = utils::get_journal_options(vm, &opts); + if (r < 0) { + return r; + } + const std::vector &args = vm[at::POSITIONAL_ARGUMENTS] .as >(); std::vector feature_names(args.begin() + 1, args.end()); @@ -76,10 +97,10 @@ int execute_enable(const po::variables_map &vm) { Shell::Action action_disable( {"feature", "disable"}, {}, "Disable the specified image feature.", "", - &get_arguments, &execute_disable); + &get_arguments_disable, &execute_disable); Shell::Action action_enable( {"feature", "enable"}, {}, "Enable the specified image feature.", "", - &get_arguments, &execute_enable); + &get_arguments_enable, &execute_enable); } // namespace feature } // namespace action diff --git a/src/tools/rbd/action/Import.cc b/src/tools/rbd/action/Import.cc index bb7cb7d86711f..e7bf4d16c828e 100644 --- a/src/tools/rbd/action/Import.cc +++ b/src/tools/rbd/action/Import.cc @@ -64,10 +64,8 @@ private: }; static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx, - const char *imgname, int *order, const char *path, - int format, uint64_t features, - uint64_t stripe_unit, uint64_t stripe_count, - bool no_progress) + const char *imgname, const char *path, + librbd::ImageOptions& opts, bool no_progress) { int fd, r; struct stat stat_buf; @@ -75,13 +73,13 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx, assert(imgname); - // default order as usual - if (*order == 0) - *order = 22; + uint64_t order; + r = opts.get(RBD_IMAGE_OPTION_ORDER, &order); + assert(r == 0); // try to fill whole imgblklen blocks for sparsification uint64_t image_pos = 0; - size_t imgblklen = 1 << *order; + size_t imgblklen = 1 << order; char *p = new char[imgblklen]; size_t reqlen = imgblklen; // amount requested from read ssize_t readlen; // amount received from one read @@ -94,7 +92,7 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx, if (from_stdin) { throttle.reset(new SimpleThrottle(1, false)); fd = 0; - size = 1ULL << *order; + size = 1ULL << order; } else { throttle.reset(new SimpleThrottle( max(g_conf->rbd_concurrent_management_ops, 1), false)); @@ -132,18 +130,27 @@ static int do_import(librbd::RBD &rbd, librados::IoCtx& io_ctx, posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); } + uint64_t format; + r = opts.get(RBD_IMAGE_OPTION_FORMAT, &format); + assert(r == 0); if (format == 1) { + uint64_t stripe_unit, stripe_count; + r = opts.get(RBD_IMAGE_OPTION_STRIPE_UNIT, &stripe_unit); + assert(r == 0); + r = opts.get(RBD_IMAGE_OPTION_STRIPE_COUNT, &stripe_count); + assert(r == 0); + // weird striping not allowed with format 1! if ((stripe_unit || stripe_count) && - (stripe_unit != (1ull << *order) && stripe_count != 1)) { + (stripe_unit != (1ull << order) && stripe_count != 1)) { std::cerr << "non-default striping not allowed with format 1; " << "use --image-format 2" << std::endl; return -EINVAL; } - r = rbd.create(io_ctx, imgname, size, order); + int order_ = order; + r = rbd.create(io_ctx, imgname, size, &order_); } else { - r = rbd.create3(io_ctx, imgname, size, features, order, - stripe_unit, stripe_count); + r = rbd.create4(io_ctx, imgname, size, opts); } if (r < 0) { std::cerr << "rbd: image creation failed" << std::endl; @@ -280,13 +287,8 @@ int execute(const po::variables_map &vm) { image_name = deprecated_image_name; } - int order; - uint32_t format; - uint64_t features; - uint32_t stripe_unit; - uint32_t stripe_count; - r = utils::get_image_options(vm, &order, &format, &features, &stripe_unit, - &stripe_count); + librbd::ImageOptions opts; + r = utils::get_image_options(vm, true, &opts); if (r < 0) { return r; } @@ -299,9 +301,8 @@ int execute(const po::variables_map &vm) { } librbd::RBD rbd; - r = do_import(rbd, io_ctx, image_name.c_str(), &order, path.c_str(), - format, features, stripe_unit, stripe_count, - vm[at::NO_PROGRESS].as()); + r = do_import(rbd, io_ctx, image_name.c_str(), path.c_str(), + opts, vm[at::NO_PROGRESS].as()); if (r < 0) { std::cerr << "rbd: import failed: " << cpp_strerror(r) << std::endl; return r; -- 2.39.5