From dc5f690b97ccdffa79fe7169bb26b0ebf06688bf Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 13 Jun 2017 22:20:55 +0200 Subject: qemu-img: Expose PreallocMode for resizing Add a --preallocation command line option to qemu-img resize which can be used to set the PreallocMode parameter of blk_truncate(). While touching this code, fix the fact that we did not handle errors returned by blk_getlength(). Signed-off-by: Max Reitz Message-id: 20170613202107.10125-5-mreitz@redhat.com Reviewed-by: Stefan Hajnoczi Signed-off-by: Max Reitz --- qemu-img.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'qemu-img.c') diff --git a/qemu-img.c b/qemu-img.c index 1b741956bc..28022145d5 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-version.h" #include "qapi/error.h" +#include "qapi/util.h" #include "qapi-visit.h" #include "qapi/qobject-output-visitor.h" #include "qapi/qmp/qerror.h" @@ -62,6 +63,7 @@ enum { OPTION_NO_DRAIN = 262, OPTION_TARGET_IMAGE_OPTS = 263, OPTION_SIZE = 264, + OPTION_PREALLOCATION = 265, }; typedef enum OutputFormat { @@ -3408,9 +3410,10 @@ static int img_resize(int argc, char **argv) Error *err = NULL; int c, ret, relative; const char *filename, *fmt, *size; - int64_t n, total_size; + int64_t n, total_size, current_size; bool quiet = false; BlockBackend *blk = NULL; + PreallocMode prealloc = PREALLOC_MODE_OFF; QemuOpts *param; static QemuOptsList resize_options = { @@ -3444,6 +3447,7 @@ static int img_resize(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"object", required_argument, 0, OPTION_OBJECT}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"preallocation", required_argument, 0, OPTION_PREALLOCATION}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, ":f:hq", @@ -3478,6 +3482,15 @@ static int img_resize(int argc, char **argv) case OPTION_IMAGE_OPTS: image_opts = true; break; + case OPTION_PREALLOCATION: + prealloc = qapi_enum_parse(PreallocMode_lookup, optarg, + PREALLOC_MODE__MAX, PREALLOC_MODE__MAX, + NULL); + if (prealloc == PREALLOC_MODE__MAX) { + error_report("Invalid preallocation mode '%s'", optarg); + return 1; + } + break; } } if (optind != argc - 1) { @@ -3526,8 +3539,16 @@ static int img_resize(int argc, char **argv) goto out; } + current_size = blk_getlength(blk); + if (current_size < 0) { + error_report("Failed to inquire current image length: %s", + strerror(-current_size)); + ret = -1; + goto out; + } + if (relative) { - total_size = blk_getlength(blk) + n * relative; + total_size = current_size + n * relative; } else { total_size = n; } @@ -3537,7 +3558,13 @@ static int img_resize(int argc, char **argv) goto out; } - ret = blk_truncate(blk, total_size, PREALLOC_MODE_OFF, &err); + if (total_size <= current_size && prealloc != PREALLOC_MODE_OFF) { + error_report("Preallocation can only be used for growing images"); + ret = -1; + goto out; + } + + ret = blk_truncate(blk, total_size, prealloc, &err); if (!ret) { qprintf(quiet, "Image resized.\n"); } else { -- cgit v1.2.1