Commit a89af8c2 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2020-05-18' into staging



nbd patches for 2020-05-20

- fix stranded fd in 'qemu-nbd -c /dev/nbd0'
- add 'qemu-img map --start-offset --max-length' options

# gpg: Signature made Mon 18 May 2020 17:29:56 BST
# gpg:                using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full]
# gpg:                 aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full]
# gpg:                 aka "[jpeg image of size 6874]" [full]
# Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2  F3AA A7A1 6B4A 2527 436A

* remotes/ericb/tags/pull-nbd-2020-05-18:
  iotests: Enhance 223 to cover qemu-img map improvements
  qemu-img: Add --start-offset and --max-length to map
  qemu-img: refactor dump_map_entry JSON format output
  qemu-img: validate image length in img_map
  qemu_img: add cvtnum_full to print error reports
  qemu-nbd: Close inherited stderr

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents a28c9c8c d8154b09
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -519,7 +519,7 @@ Command description:
    ``ImageInfoSpecific*`` QAPI object (e.g. ``ImageInfoSpecificQCow2``
    for qcow2 images).

.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME
.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME

  Dump the metadata of image *FILENAME* and its backing file chain.
  In particular, this commands dumps the allocation state of every sector
+2 −2
Original line number Diff line number Diff line
@@ -63,9 +63,9 @@ SRST
ERST

DEF("map", img_map,
    "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-U] filename")
    "map [--object objectdef] [--image-opts] [-f fmt] [--start-offset=offset] [--max-length=len] [--output=ofmt] [-U] filename")
SRST
.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME
.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME
ERST

DEF("measure", img_measure,
+68 −47
Original line number Diff line number Diff line
@@ -470,19 +470,31 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
    return 0;
}

static int64_t cvtnum(const char *s)
static int64_t cvtnum_full(const char *name, const char *value, int64_t min,
                           int64_t max)
{
    int err;
    uint64_t value;
    uint64_t res;

    err = qemu_strtosz(s, NULL, &value);
    if (err < 0) {
    err = qemu_strtosz(value, NULL, &res);
    if (err < 0 && err != -ERANGE) {
        error_report("Invalid %s specified. You may use "
                     "k, M, G, T, P or E suffixes for", name);
        error_report("kilobytes, megabytes, gigabytes, terabytes, "
                     "petabytes and exabytes.");
        return err;
    }
    if (value > INT64_MAX) {
    if (err == -ERANGE || res > max || res < min) {
        error_report("Invalid %s specified. Must be between %" PRId64
                     " and %" PRId64 ".", name, min, max);
        return -ERANGE;
    }
    return value;
    return res;
}

static int64_t cvtnum(const char *name, const char *value)
{
    return cvtnum_full(name, value, 0, INT64_MAX);
}

static int img_create(int argc, char **argv)
@@ -572,16 +584,8 @@ static int img_create(int argc, char **argv)
    if (optind < argc) {
        int64_t sval;

        sval = cvtnum(argv[optind++]);
        sval = cvtnum("image size", argv[optind++]);
        if (sval < 0) {
            if (sval == -ERANGE) {
                error_report("Image size must be less than 8 EiB!");
            } else {
                error_report("Invalid image size specified! You may use k, M, "
                      "G, T, P or E suffixes for ");
                error_report("kilobytes, megabytes, gigabytes, terabytes, "
                             "petabytes and exabytes.");
            }
            goto fail;
        }
        img_size = (uint64_t)sval;
@@ -2187,8 +2191,10 @@ static int img_convert(int argc, char **argv)
        {
            int64_t sval;

            sval = cvtnum(optarg);
            if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
            sval = cvtnum("buffer size for sparse output", optarg);
            if (sval < 0) {
                goto fail_getopt;
            } else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
                sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) {
                error_report("Invalid buffer size for sparse output specified. "
                    "Valid sizes are multiples of %llu up to %llu. Select "
@@ -2896,9 +2902,8 @@ static int dump_map_entry(OutputFormat output_format, MapEntry *e,
        }
        break;
    case OFORMAT_JSON:
        printf("%s{ \"start\": %"PRId64", \"length\": %"PRId64","
        printf("{ \"start\": %"PRId64", \"length\": %"PRId64","
               " \"depth\": %"PRId64", \"zero\": %s, \"data\": %s",
               (e->start == 0 ? "[" : ",\n"),
               e->start, e->length, e->depth,
               e->zero ? "true" : "false",
               e->data ? "true" : "false");
@@ -2907,8 +2912,8 @@ static int dump_map_entry(OutputFormat output_format, MapEntry *e,
        }
        putchar('}');

        if (!next) {
            printf("]\n");
        if (next) {
            puts(",");
        }
        break;
    }
@@ -3004,6 +3009,8 @@ static int img_map(int argc, char **argv)
    int ret = 0;
    bool image_opts = false;
    bool force_share = false;
    int64_t start_offset = 0;
    int64_t max_length = -1;

    fmt = NULL;
    output = NULL;
@@ -3016,9 +3023,11 @@ static int img_map(int argc, char **argv)
            {"object", required_argument, 0, OPTION_OBJECT},
            {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
            {"force-share", no_argument, 0, 'U'},
            {"start-offset", required_argument, 0, 's'},
            {"max-length", required_argument, 0, 'l'},
            {0, 0, 0, 0}
        };
        c = getopt_long(argc, argv, ":f:hU",
        c = getopt_long(argc, argv, ":f:s:l:hU",
                        long_options, &option_index);
        if (c == -1) {
            break;
@@ -3042,6 +3051,18 @@ static int img_map(int argc, char **argv)
        case OPTION_OUTPUT:
            output = optarg;
            break;
        case 's':
            start_offset = cvtnum("start offset", optarg);
            if (start_offset < 0) {
                return 1;
            }
            break;
        case 'l':
            max_length = cvtnum("max length", optarg);
            if (max_length < 0) {
                return 1;
            }
            break;
        case OPTION_OBJECT: {
            QemuOpts *opts;
            opts = qemu_opts_parse_noisily(&qemu_object_opts,
@@ -3083,9 +3104,20 @@ static int img_map(int argc, char **argv)

    if (output_format == OFORMAT_HUMAN) {
        printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
    } else if (output_format == OFORMAT_JSON) {
        putchar('[');
    }

    length = blk_getlength(blk);
    if (length < 0) {
        error_report("Failed to get size for '%s'", filename);
        return 1;
    }
    if (max_length != -1) {
        length = MIN(start_offset + max_length, length);
    }

    curr.start = start_offset;
    while (curr.start + curr.length < length) {
        int64_t offset = curr.start + curr.length;
        int64_t n;
@@ -3114,6 +3146,9 @@ static int img_map(int argc, char **argv)
    }

    ret = dump_map_entry(output_format, &curr, NULL);
    if (output_format == OFORMAT_JSON) {
        puts("]");
    }

out:
    blk_unref(blk);
@@ -4291,9 +4326,8 @@ static int img_bench(int argc, char **argv)
            break;
        case 'o':
        {
            offset = cvtnum(optarg);
            offset = cvtnum("offset", optarg);
            if (offset < 0) {
                error_report("Invalid offset specified");
                return 1;
            }
            break;
@@ -4306,9 +4340,8 @@ static int img_bench(int argc, char **argv)
        {
            int64_t sval;

            sval = cvtnum(optarg);
            if (sval < 0 || sval > INT_MAX) {
                error_report("Invalid buffer size specified");
            sval = cvtnum_full("buffer size", optarg, 0, INT_MAX);
            if (sval < 0) {
                return 1;
            }

@@ -4319,9 +4352,8 @@ static int img_bench(int argc, char **argv)
        {
            int64_t sval;

            sval = cvtnum(optarg);
            if (sval < 0 || sval > INT_MAX) {
                error_report("Invalid step size specified");
            sval = cvtnum_full("step_size", optarg, 0, INT_MAX);
            if (sval < 0) {
                return 1;
            }

@@ -4491,10 +4523,9 @@ static int img_dd_bs(const char *arg,
{
    int64_t res;

    res = cvtnum(arg);
    res = cvtnum_full("bs", arg, 1, INT_MAX);

    if (res <= 0 || res > INT_MAX) {
        error_report("invalid number: '%s'", arg);
    if (res < 0) {
        return 1;
    }
    in->bsz = out->bsz = res;
@@ -4506,10 +4537,9 @@ static int img_dd_count(const char *arg,
                        struct DdIo *in, struct DdIo *out,
                        struct DdInfo *dd)
{
    dd->count = cvtnum(arg);
    dd->count = cvtnum("count", arg);

    if (dd->count < 0) {
        error_report("invalid number: '%s'", arg);
        return 1;
    }

@@ -4538,10 +4568,9 @@ static int img_dd_skip(const char *arg,
                       struct DdIo *in, struct DdIo *out,
                       struct DdInfo *dd)
{
    in->offset = cvtnum(arg);
    in->offset = cvtnum("skip", arg);

    if (in->offset < 0) {
        error_report("invalid number: '%s'", arg);
        return 1;
    }

@@ -4923,16 +4952,8 @@ static int img_measure(int argc, char **argv)
        {
            int64_t sval;

            sval = cvtnum(optarg);
            sval = cvtnum("image size", optarg);
            if (sval < 0) {
                if (sval == -ERANGE) {
                    error_report("Image size must be less than 8 EiB!");
                } else {
                    error_report("Invalid image size specified! You may use "
                                 "k, M, G, T, P or E suffixes for ");
                    error_report("kilobytes, megabytes, gigabytes, terabytes, "
                                 "petabytes and exabytes.");
                }
                goto out;
            }
            img_size = (uint64_t)sval;
+5 −1
Original line number Diff line number Diff line
@@ -916,7 +916,11 @@ int main(int argc, char **argv)
        } else if (pid == 0) {
            close(stderr_fd[0]);

            /* Remember parent's stderr if we will be restoring it. */
            if (fork_process) {
                old_stderr = dup(STDERR_FILENO);
            }

            ret = qemu_daemon(1, 0);

            /* Temporarily redirect stderr to the parent's pipe...  */
+4 −4
Original line number Diff line number Diff line
@@ -92,19 +92,19 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 l
== 3. Invalid sizes ==

qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024
qemu-img: Image size must be less than 8 EiB!
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.

qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size'

qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k
qemu-img: Image size must be less than 8 EiB!
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.

qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Value '-1k' is out of range for parameter 'size'

qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.

qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
@@ -113,7 +113,7 @@ Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta-
and exabytes, respectively.

qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.

qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
Loading