From be2cdc0bcf7a395d7ccf53c4c87aa7097deaa8f8 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Tue, 29 Jan 2019 11:44:54 +0000 Subject: [PATCH] rbd: online re-sparsify of images Signed-off-by: Mykola Golub --- doc/man/8/rbd.rst | 6 +++ qa/workunits/rbd/cli_generic.sh | 3 ++ src/test/cli/rbd/help.t | 20 ++++++++ src/tools/rbd/CMakeLists.txt | 1 + src/tools/rbd/action/Sparsify.cc | 82 ++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 src/tools/rbd/action/Sparsify.cc diff --git a/doc/man/8/rbd.rst b/doc/man/8/rbd.rst index 928dda028e558..22f78ad63d555 100644 --- a/doc/man/8/rbd.rst +++ b/doc/man/8/rbd.rst @@ -607,6 +607,12 @@ Commands This requires image format 2. +:command:`sparsify` [--sparse-size *sparse-size*] *image-spec* + Reclaim space for zeroed image extents. The default sparse size is + 4096 bytes and can be changed via --sparse-size option with the + following restrictions: it should be power of two, not less than + 4096, and not larger image object size. + :command:`status` *image-spec* Show the status of the image, including which clients have it open. diff --git a/qa/workunits/rbd/cli_generic.sh b/qa/workunits/rbd/cli_generic.sh index 8f2a25a8e9551..97d64577fad5b 100755 --- a/qa/workunits/rbd/cli_generic.sh +++ b/qa/workunits/rbd/cli_generic.sh @@ -125,6 +125,9 @@ test_others() { rbd info --snap=snap1 testimg1 2>&1 | grep 'error setting snapshot context: (2) No such file or directory' rbd info --snap=snap1 testimg-diff1 2>&1 | grep 'error setting snapshot context: (2) No such file or directory' + # sparsify + rbd sparsify testimg1 + remove_images rm -f $TMP_FILES } diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 233891d908650..76ea32829e1bd 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -123,6 +123,7 @@ snap rename Rename a snapshot. snap rollback (snap revert) Rollback image to snapshot. snap unprotect Allow a snapshot to be deleted. + sparsify Reclaim space for zeroed image extents. status Show the status of this image. trash list (trash ls) List trash images. trash move (trash mv) Move an image to the trash. @@ -2165,6 +2166,25 @@ --snap arg snapshot name --image-id arg image id + rbd help sparsify + usage: rbd sparsify [--pool ] [--namespace ] + [--image ] [--no-progress] + [--sparse-size ] + + + Reclaim space for zeroed image extents. + + Positional arguments + image specification + (example: [/[/]]) + + Optional arguments + -p [ --pool ] arg pool name + --namespace arg namespace name + --image arg image name + --no-progress disable progress output + --sparse-size arg sparse size in B/K/M [default: 4K] + rbd help status usage: rbd status [--pool ] [--namespace ] [--image ] [--format ] [--pretty-format] diff --git a/src/tools/rbd/CMakeLists.txt b/src/tools/rbd/CMakeLists.txt index 6679769c0bf2b..eaebbc8f11433 100644 --- a/src/tools/rbd/CMakeLists.txt +++ b/src/tools/rbd/CMakeLists.txt @@ -40,6 +40,7 @@ set(rbd_srcs action/Rename.cc action/Resize.cc action/Snap.cc + action/Sparsify.cc action/Status.cc action/Trash.cc action/Watch.cc) diff --git a/src/tools/rbd/action/Sparsify.cc b/src/tools/rbd/action/Sparsify.cc new file mode 100644 index 0000000000000..a345f920b3eeb --- /dev/null +++ b/src/tools/rbd/action/Sparsify.cc @@ -0,0 +1,82 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "tools/rbd/ArgumentTypes.h" +#include "tools/rbd/Shell.h" +#include "tools/rbd/Utils.h" +#include "common/errno.h" +#include +#include + +namespace rbd { +namespace action { +namespace sparsify { + +namespace at = argument_types; +namespace po = boost::program_options; + +static int do_sparsify(librbd::Image& image, size_t sparse_size, + bool no_progress) +{ + utils::ProgressContext pc("Image sparsify", no_progress); + int r = image.sparsify_with_progress(sparse_size, pc); + if (r < 0) { + pc.fail(); + return r; + } + pc.finish(); + return 0; +} + +void get_arguments(po::options_description *positional, + po::options_description *options) { + at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); + at::add_no_progress_option(options); + at::add_sparse_size_option(options); +} + +int execute(const po::variables_map &vm, + const std::vector &ceph_global_init_args) { + size_t arg_index = 0; + std::string pool_name; + std::string namespace_name; + std::string image_name; + std::string snap_name; + int r = utils::get_pool_image_snapshot_names( + vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name, + &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE, + utils::SPEC_VALIDATION_NONE); + if (r < 0) { + return r; + } + + librados::Rados rados; + librados::IoCtx io_ctx; + librbd::Image image; + r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "", + false, &rados, &io_ctx, &image); + if (r < 0) { + return r; + } + + size_t sparse_size = utils::RBD_DEFAULT_SPARSE_SIZE; + if (vm.count(at::IMAGE_SPARSE_SIZE)) { + sparse_size = vm[at::IMAGE_SPARSE_SIZE].as(); + } + + r = do_sparsify(image, sparse_size, vm[at::NO_PROGRESS].as()); + if (r < 0) { + std::cerr << "rbd: sparsify error: " << cpp_strerror(r) << std::endl; + return r; + } + return 0; +} + +Shell::Action action( + {"sparsify"}, {}, + "Reclaim space for zeroed image extents.", "", + &get_arguments, &execute); + +} // namespace sparsify +} // namespace action +} // namespace rbd -- 2.39.5