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 <mreitz@redhat.com>
Message-id: 20170613202107.10125-5-mreitz@redhat.com
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Max Reitz 2017-06-13 22:20:55 +02:00
parent 3a691c50f1
commit dc5f690b97
2 changed files with 36 additions and 4 deletions

View File

@ -24,6 +24,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-version.h" #include "qemu-version.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/util.h"
#include "qapi-visit.h" #include "qapi-visit.h"
#include "qapi/qobject-output-visitor.h" #include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
@ -62,6 +63,7 @@ enum {
OPTION_NO_DRAIN = 262, OPTION_NO_DRAIN = 262,
OPTION_TARGET_IMAGE_OPTS = 263, OPTION_TARGET_IMAGE_OPTS = 263,
OPTION_SIZE = 264, OPTION_SIZE = 264,
OPTION_PREALLOCATION = 265,
}; };
typedef enum OutputFormat { typedef enum OutputFormat {
@ -3408,9 +3410,10 @@ static int img_resize(int argc, char **argv)
Error *err = NULL; Error *err = NULL;
int c, ret, relative; int c, ret, relative;
const char *filename, *fmt, *size; const char *filename, *fmt, *size;
int64_t n, total_size; int64_t n, total_size, current_size;
bool quiet = false; bool quiet = false;
BlockBackend *blk = NULL; BlockBackend *blk = NULL;
PreallocMode prealloc = PREALLOC_MODE_OFF;
QemuOpts *param; QemuOpts *param;
static QemuOptsList resize_options = { static QemuOptsList resize_options = {
@ -3444,6 +3447,7 @@ static int img_resize(int argc, char **argv)
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"preallocation", required_argument, 0, OPTION_PREALLOCATION},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, ":f:hq", c = getopt_long(argc, argv, ":f:hq",
@ -3478,6 +3482,15 @@ static int img_resize(int argc, char **argv)
case OPTION_IMAGE_OPTS: case OPTION_IMAGE_OPTS:
image_opts = true; image_opts = true;
break; 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) { if (optind != argc - 1) {
@ -3526,8 +3539,16 @@ static int img_resize(int argc, char **argv)
goto out; 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) { if (relative) {
total_size = blk_getlength(blk) + n * relative; total_size = current_size + n * relative;
} else { } else {
total_size = n; total_size = n;
} }
@ -3537,7 +3558,13 @@ static int img_resize(int argc, char **argv)
goto out; 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) { if (!ret) {
qprintf(quiet, "Image resized.\n"); qprintf(quiet, "Image resized.\n");
} else { } else {

View File

@ -529,7 +529,7 @@ qemu-img rebase -b base.img diff.qcow2
At this point, @code{modified.img} can be discarded, since At this point, @code{modified.img} can be discarded, since
@code{base.img + diff.qcow2} contains the same information. @code{base.img + diff.qcow2} contains the same information.
@item resize @var{filename} [+ | -]@var{size} @item resize [--preallocation=@var{prealloc}] @var{filename} [+ | -]@var{size}
Change the disk image as if it had been created with @var{size}. Change the disk image as if it had been created with @var{size}.
@ -541,6 +541,11 @@ After using this command to grow a disk image, you must use file system and
partitioning tools inside the VM to actually begin using the new space on the partitioning tools inside the VM to actually begin using the new space on the
device. device.
When growing an image, the @code{--preallocation} option may be used to specify
how the additional image area should be allocated on the host. See the format
description in the @code{NOTES} section which values are allowed. Using this
option may result in slightly more data being allocated than necessary.
@item amend [-p] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} @item amend [-p] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
Amends the image format specific @var{options} for the image file Amends the image format specific @var{options} for the image file