Commit 6e6e55f5 authored by John Snow's avatar John Snow Committed by Kevin Wolf
Browse files

qemu-img: Check for backing image if specified during create

Or, rather, force the open of a backing image if one was specified
for creation. Using a similar -unsafe option as rebase, allow qemu-img
to ignore the backing file validation if possible.

It may not always be possible, as in the existing case when a filesize
for the new image was not specified.

This is accomplished by shifting around the conditionals in
bdrv_img_create, such that a backing file is always opened unless we
provide BDRV_O_NO_BACKING. qemu-img is adjusted to pass this new flag
when -u is provided to create.

Sorry for the heinous looking diffstat, but it's mostly whitespace.

Inspired by: https://bugzilla.redhat.com/show_bug.cgi?id=1213786



Signed-off-by: default avatarJohn Snow <jsnow@redhat.com>
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent 2a32c6e8
Loading
Loading
Loading
Loading
+52 −42
Original line number Diff line number Diff line
@@ -4396,14 +4396,12 @@ void bdrv_img_create(const char *filename, const char *fmt,

    backing_fmt = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);

    // The size for the image must always be specified, with one exception:
    // If we are using a backing file, we can obtain the size from there
    /* The size for the image must always be specified, unless we have a backing
     * file and we have not been forbidden from opening it. */
    size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
    if (size == -1) {
        if (backing_file) {
    if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
        BlockDriverState *bs;
        char *full_backing = g_new0(char, PATH_MAX);
            int64_t size;
        int back_flags;
        QDict *backing_options = NULL;

@@ -4427,9 +4425,20 @@ void bdrv_img_create(const char *filename, const char *fmt,
        bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
                       &local_err);
        g_free(full_backing);
            if (!bs) {
        if (!bs && size != -1) {
            /* Couldn't open BS, but we have a size, so it's nonfatal */
            warn_reportf_err(local_err,
                            "Could not verify backing image. "
                            "This may become an error in future versions.\n");
            local_err = NULL;
        } else if (!bs) {
            /* Couldn't open bs, do not have size */
            error_append_hint(&local_err,
                              "Could not open backing image to determine size.\n");
            goto out;
            }
        } else {
            if (size == -1) {
                /* Opened BS, have no size */
                size = bdrv_getlength(bs);
                if (size < 0) {
                    error_setg_errno(errp, -size, "Could not get size of '%s'",
@@ -4437,15 +4446,16 @@ void bdrv_img_create(const char *filename, const char *fmt,
                    bdrv_unref(bs);
                    goto out;
                }

                qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);

            }
            bdrv_unref(bs);
        } else {
        }
    } /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */

    if (size == -1) {
        error_setg(errp, "Image creation needs a size parameter");
        goto out;
    }
    }

    if (!quiet) {
        printf("Formatting '%s', fmt=%s ", filename, fmt);
+2 −2
Original line number Diff line number Diff line
@@ -22,9 +22,9 @@ STEXI
ETEXI

DEF("create", img_create,
    "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-o options] filename [size]")
    "create [-q] [--object objectdef] [-f fmt] [-b backing_file] [-F backing_fmt] [-u] [-o options] filename [size]")
STEXI
@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}]
ETEXI

DEF("commit", img_commit,
+11 −5
Original line number Diff line number Diff line
@@ -150,9 +150,11 @@ static void QEMU_NORETURN help(void)
           "  'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
           "    instead\n"
           "  '-c' indicates that target image must be compressed (qcow format only)\n"
           "  '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
           "       match exactly. The image doesn't need a working backing file before\n"
           "       rebasing in this case (useful for renaming the backing file)\n"
           "  '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
           "       new backing file match exactly. The image doesn't need a working\n"
           "       backing file before rebasing in this case (useful for renaming the\n"
           "       backing file). For image creation, allow creating without attempting\n"
           "       to open the backing file.\n"
           "  '-h' with or without a command shows this help and lists the supported formats\n"
           "  '-p' show progress of command (only certain commands)\n"
           "  '-q' use Quiet mode - do not print any output (except errors)\n"
@@ -429,6 +431,7 @@ static int img_create(int argc, char **argv)
    char *options = NULL;
    Error *local_err = NULL;
    bool quiet = false;
    int flags = 0;

    for(;;) {
        static const struct option long_options[] = {
@@ -436,7 +439,7 @@ static int img_create(int argc, char **argv)
            {"object", required_argument, 0, OPTION_OBJECT},
            {0, 0, 0, 0}
        };
        c = getopt_long(argc, argv, ":F:b:f:ho:q",
        c = getopt_long(argc, argv, ":F:b:f:ho:qu",
                        long_options, NULL);
        if (c == -1) {
            break;
@@ -476,6 +479,9 @@ static int img_create(int argc, char **argv)
        case 'q':
            quiet = true;
            break;
        case 'u':
            flags |= BDRV_O_NO_BACKING;
            break;
        case OPTION_OBJECT: {
            QemuOpts *opts;
            opts = qemu_opts_parse_noisily(&qemu_object_opts,
@@ -528,7 +534,7 @@ static int img_create(int argc, char **argv)
    }

    bdrv_img_create(filename, fmt, base_filename, base_fmt,
                    options, img_size, 0, quiet, &local_err);
                    options, img_size, flags, quiet, &local_err);
    if (local_err) {
        error_reportf_err(local_err, "%s: ", filename);
        goto fail;
+8 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ If @code{-r} is specified, exit codes representing the image state refer to the
state after (the attempt at) repairing it. That is, a successful @code{-r all}
will yield the exit code 0, independently of the image state before.

@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-o @var{options}] @var{filename} [@var{size}]
@item create [-f @var{fmt}] [-b @var{backing_file}] [-F @var{backing_fmt}] [-u] [-o @var{options}] @var{filename} [@var{size}]

Create the new disk image @var{filename} of size @var{size} and format
@var{fmt}. Depending on the file format, you can add one or more @var{options}
@@ -244,6 +244,13 @@ only the differences from @var{backing_file}. No size needs to be specified in
this case. @var{backing_file} will never be modified unless you use the
@code{commit} monitor command (or qemu-img commit).

Note that a given backing file will be opened to check that it is valid. Use
the @code{-u} option to enable unsafe backing file mode, which means that the
image will be created even if the associated backing file cannot be opened. A
matching backing file must be created or additional options be used to make the
backing file specification valid when you want to use an image created this
way.

The size can also be specified using the @var{size} option with @code{-o},
it doesn't need to be specified separately in this case.

+2 −2
Original line number Diff line number Diff line
@@ -85,8 +85,8 @@ run_qemu_img create -f $IMGFMT -o cluster_size=4k -o help "$TEST_IMG" $size
run_qemu_img create -f $IMGFMT -o cluster_size=4k -o \? "$TEST_IMG" $size

# Looks like a help option, but is part of the backing file name
run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size
run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size
run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,help "$TEST_IMG" $size
run_qemu_img create -f $IMGFMT -u -o backing_file="$TEST_IMG",,\? "$TEST_IMG" $size

# Try to trick qemu-img into creating escaped commas
run_qemu_img create -f $IMGFMT -o backing_file="$TEST_IMG", -o help "$TEST_IMG" $size
Loading