qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: Max Reitz <mreitz@redhat.com>
Cc: qemu-devel@nongnu.org, Kevin Wolf <kwolf@redhat.com>,
	John Snow <jsnow@redhat.com>, Nir Soffer <nsoffer@redhat.com>,
	Maor Lipchuk <mlipchuk@redhat.com>,
	Alberto Garcia <berto@igalia.com>
Subject: Re: [Qemu-devel] [RFC v2 6/8] qemu-img: add measure subcommand
Date: Thu, 16 Mar 2017 11:45:09 +0800	[thread overview]
Message-ID: <20170316034509.GL11074@stefanha-x1.localdomain> (raw)
In-Reply-To: <2b0e4c7b-254e-2b58-ab35-a73545e3671a@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 7464 bytes --]

On Thu, Mar 16, 2017 at 02:46:12AM +0100, Max Reitz wrote:
> On 15.03.2017 10:29, Stefan Hajnoczi wrote:
> > The measure subcommand calculates the size required by a new image file.
> > This can be used by users or management tools that need to allocate
> > space on an LVM volume, SAN LUN, etc before creating or converting an
> > image file.
> > 
> > Suggested-by: Maor Lipchuk <mlipchuk@redhat.com>
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  qemu-img.c       | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  qemu-img-cmds.hx |   9 +++
> 
> Looking forward to the documentation in the non-RFC version. O:-)

Thanks for reminding me that the qemu-img man page needs documentation
for this new sub-command :).

> >  2 files changed, 222 insertions(+)
> > 
> > diff --git a/qemu-img.c b/qemu-img.c
> > index 98b836b..e8c6dcc 100644
> > --- a/qemu-img.c
> > +++ b/qemu-img.c
> > @@ -59,6 +59,7 @@ enum {
> >      OPTION_PATTERN = 260,
> >      OPTION_FLUSH_INTERVAL = 261,
> >      OPTION_NO_DRAIN = 262,
> > +    OPTION_SIZE = 263,
> >  };
> >  
> >  typedef enum OutputFormat {
> > @@ -4287,6 +4288,218 @@ out:
> >      return 0;
> >  }
> >  
> > +static void dump_json_block_measure_info(BlockMeasureInfo *info)
> > +{
> > +    QString *str;
> > +    QObject *obj;
> > +    Visitor *v = qobject_output_visitor_new(&obj);
> > +
> > +    visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort);
> > +    visit_complete(v, &obj);
> > +    str = qobject_to_json_pretty(obj);
> > +    assert(str != NULL);
> > +    printf("%s\n", qstring_get_str(str));
> > +    qobject_decref(obj);
> > +    visit_free(v);
> > +    QDECREF(str);
> > +}
> > +
> > +static int img_measure(int argc, char **argv)
> > +{
> > +    static const struct option long_options[] = {
> > +        {"help", no_argument, 0, 'h'},
> > +        {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
> > +        {"object", required_argument, 0, OPTION_OBJECT},
> > +        {"output", required_argument, 0, OPTION_OUTPUT},
> > +        {"size", required_argument, 0, OPTION_SIZE},
> > +        {0, 0, 0, 0}
> > +    };
> > +    OutputFormat output_format = OFORMAT_HUMAN;
> > +    BlockBackend *in_blk = NULL;
> > +    BlockDriver *drv;
> > +    const char *filename = NULL;
> > +    const char *fmt = NULL;
> > +    const char *out_fmt = "raw";
> > +    char *options = NULL;
> > +    char *snapshot_name = NULL;
> > +    QemuOpts *opts = NULL;
> > +    QemuOpts *object_opts = NULL;
> > +    QemuOpts *sn_opts = NULL;
> > +    QemuOptsList *create_opts = NULL;
> > +    bool image_opts = false;
> > +    uint64_t img_size = ~0ULL;
> > +    BlockMeasureInfo info;
> > +    Error *local_err = NULL;
> > +    int ret = 1;
> > +    int c;
> > +
> > +    while ((c = getopt_long(argc, argv, "hf:O:o:l:",
> > +                            long_options, NULL)) != -1) {
> > +        switch (c) {
> > +        case '?':
> > +        case 'h':
> > +            help();
> > +            break;
> > +        case 'f':
> > +            fmt = optarg;
> > +            break;
> > +        case 'O':
> > +            out_fmt = optarg;
> > +            break;
> > +        case 'o':
> > +            if (!is_valid_option_list(optarg)) {
> > +                error_report("Invalid option list: %s", optarg);
> > +                goto out;
> > +            }
> > +            if (!options) {
> > +                options = g_strdup(optarg);
> > +            } else {
> > +                char *old_options = options;
> > +                options = g_strdup_printf("%s,%s", options, optarg);
> > +                g_free(old_options);
> > +            }
> > +            break;
> > +        case 'l':
> > +            if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
> > +                sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts,
> > +                                                  optarg, false);
> > +                if (!sn_opts) {
> > +                    error_report("Failed in parsing snapshot param '%s'",
> > +                                 optarg);
> > +                    goto out;
> > +                }
> > +            } else {
> > +                snapshot_name = optarg;
> > +            }
> > +            break;
> > +        case OPTION_OBJECT:
> > +            object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
> > +                                                  optarg, true);
> > +            if (!object_opts) {
> > +                goto out;
> > +            }
> > +            break;
> > +        case OPTION_IMAGE_OPTS:
> > +            image_opts = true;
> > +            break;
> > +        case OPTION_OUTPUT:
> > +            if (!strcmp(optarg, "json")) {
> > +                output_format = OFORMAT_JSON;
> > +            } else if (!strcmp(optarg, "human")) {
> > +                output_format = OFORMAT_HUMAN;
> > +            } else {
> > +                error_report("--output must be used with human or json "
> > +                             "as argument.");
> > +                goto out;
> > +            }
> > +            break;
> > +        case OPTION_SIZE:
> > +        {
> > +            int64_t sval;
> > +
> > +            sval = cvtnum(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.");
> 
> BTW, I love how we say "EiB" in these error messages but the non-i
> suffixes the user can specify are still power-of-two units.
> 
> (Also, this error message explicitly says "kilobytes" and so on instead
> of "kibibytes". I'm fine with it not least because it's pre-existing,
> though. (Furthermore, I'd rather have it be "EB" than the latter message
> contain "kibibytes, mebibytes" and so on.))
> 
> > +                }
> > +                goto out;
> > +            }
> > +            img_size = (uint64_t)sval;
> > +        }
> > +        break;
> > +        }
> > +    }
> > +
> > +    if (qemu_opts_foreach(&qemu_object_opts,
> > +                          user_creatable_add_opts_foreach,
> > +                          NULL, NULL)) {
> > +        goto out;
> > +    }
> > +
> > +    if (argc - optind > 1) {
> > +        error_report("At most one filename argument is allowed.");
> 
> Not exactly like convert, then. :-(
> 
> But, yeah, it wouldn't really work for the current interface and we can
> always extend it later.
> 
> (But maybe that means the interface could be better. Maybe this central
> function here could collect a statistics of allocated/zero/free/...
> clusters of the input image (with a cluster size somehow specified by
> the output image driver, however that's supposed to work...) and pass it
> to the output driver. That would also save us from replicating the input
> block query code for all of the block drivers that implement
> bdrv_measure().)

I will look into this for the next revision, thanks.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

  reply	other threads:[~2017-03-16  3:45 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-15  9:29 [Qemu-devel] [RFC v2 0/8] qemu-img: add measure sub-command Stefan Hajnoczi
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 1/8] block: add bdrv_measure() API Stefan Hajnoczi
2017-03-16  1:01   ` Max Reitz
2017-03-16  3:38     ` Stefan Hajnoczi
2017-03-16  4:02       ` Max Reitz
2017-03-18  0:51   ` Nir Soffer
2017-03-20 15:37     ` Stefan Hajnoczi
2017-03-18  1:28   ` Nir Soffer
2017-03-20 15:34     ` Stefan Hajnoczi
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 2/8] raw-format: add bdrv_measure() support Stefan Hajnoczi
2017-03-18  1:11   ` Nir Soffer
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 3/8] qcow2: extract preallocation calculation function Stefan Hajnoczi
2017-03-16  1:18   ` Max Reitz
2017-03-16  3:40     ` Stefan Hajnoczi
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 4/8] qcow2: extract image creation option parsing Stefan Hajnoczi
2017-03-18 20:14   ` Nir Soffer
2017-03-20 15:40     ` Stefan Hajnoczi
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 5/8] qcow2: add bdrv_measure() support Stefan Hajnoczi
2017-03-16  1:57   ` Max Reitz
2017-03-16  3:41     ` Stefan Hajnoczi
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 6/8] qemu-img: add measure subcommand Stefan Hajnoczi
2017-03-16  1:46   ` Max Reitz
2017-03-16  3:45     ` Stefan Hajnoczi [this message]
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 7/8] qemu-iotests: support per-format golden output files Stefan Hajnoczi
2017-03-16  1:51   ` Max Reitz
2017-03-15  9:29 ` [Qemu-devel] [RFC v2 8/8] iotests: add test 178 for qemu-img measure Stefan Hajnoczi
2017-03-18 21:04   ` Nir Soffer
2017-03-20 15:43     ` Stefan Hajnoczi
2017-03-17 23:45 ` [Qemu-devel] [RFC v2 0/8] qemu-img: add measure sub-command Nir Soffer
2017-03-20 15:51   ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170316034509.GL11074@stefanha-x1.localdomain \
    --to=stefanha@redhat.com \
    --cc=berto@igalia.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mlipchuk@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=nsoffer@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).