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 --]
next prev parent 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).