Message ID | 1350050969-14034-1-git-send-email-stefanha@redhat.com |
---|---|
State | New |
Headers | show |
On Fri, Oct 12, 2012 at 7:39 PM, Stefan Hajnoczi <stefanha@redhat.com> wrote: > The qemu-img info --backing-chain option enumerates the backing file > chain. For example, for base.qcow2 <- snap1.qcow2 <- snap2.qcow2 the > output becomes: > > $ qemu-img info --backing-chain snap2.qcow2 > image: snap2.qcow2 > file format: qcow2 > virtual size: 100M (104857600 bytes) > disk size: 196K > cluster_size: 65536 > backing file: snap1.qcow2 > backing file format: qcow2 > > image: snap1.qcow2 > file format: qcow2 > virtual size: 100M (104857600 bytes) > disk size: 196K > cluster_size: 65536 > backing file: base.qcow2 > backing file format: qcow2 > > image: base.qcow2 > file format: qcow2 > virtual size: 100M (104857600 bytes) > disk size: 136K > cluster_size: 65536 > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > --- > qemu-img.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 76 insertions(+), 22 deletions(-) > > diff --git a/qemu-img.c b/qemu-img.c > index f17f187..c717f3e 100644 > --- a/qemu-img.c > +++ b/qemu-img.c > @@ -1249,7 +1249,10 @@ static void dump_human_image_info(ImageInfo *info) > } > } > > -enum {OPTION_OUTPUT = 256}; > +enum { > + OPTION_OUTPUT = 256, > + OPTION_BACKING_CHAIN = 257, > +}; > > typedef enum OutputFormat { > OFORMAT_JSON, > @@ -1260,7 +1263,9 @@ static int img_info(int argc, char **argv) > { > int c; > OutputFormat output_format = OFORMAT_HUMAN; > - const char *filename, *fmt, *output; > + bool chain = false; > + const char *output; > + char *filename, *fmt; > BlockDriverState *bs; > ImageInfo *info; > > @@ -1272,6 +1277,7 @@ static int img_info(int argc, char **argv) > {"help", no_argument, 0, 'h'}, > {"format", required_argument, 0, 'f'}, > {"output", required_argument, 0, OPTION_OUTPUT}, > + {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, > {0, 0, 0, 0} > }; > c = getopt_long(argc, argv, "f:h", > @@ -1285,17 +1291,20 @@ static int img_info(int argc, char **argv) > help(); > break; > case 'f': > - fmt = optarg; > + fmt = g_strdup(optarg); > break; > case OPTION_OUTPUT: > output = optarg; > break; > + case OPTION_BACKING_CHAIN: > + chain = true; > + break; > } > } > if (optind >= argc) { > help(); > } > - filename = argv[optind++]; > + filename = g_strdup(argv[optind++]); > > if (output && !strcmp(output, "json")) { > output_format = OFORMAT_JSON; > @@ -1303,31 +1312,76 @@ static int img_info(int argc, char **argv) > output_format = OFORMAT_HUMAN; > } else if (output) { > error_report("--output must be used with human or json as argument."); > - return 1; > + goto err; > } > > - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false); > - if (!bs) { > - return 1; > + if (chain && output_format == OFORMAT_JSON) { > + printf("[\n"); > } > > - info = g_new0(ImageInfo, 1); > - collect_image_info(bs, info, filename, fmt); > + do { > + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, > + false); > + if (!bs) { > + goto err; > + } > > - switch (output_format) { > - case OFORMAT_HUMAN: > - dump_human_image_info(info); > - dump_snapshots(bs); > - break; > - case OFORMAT_JSON: > - collect_snapshots(bs, info); > - dump_json_image_info(info); > - break; > - } > + info = g_new0(ImageInfo, 1); > + collect_image_info(bs, info, filename, fmt); > > - qapi_free_ImageInfo(info); > - bdrv_delete(bs); > + switch (output_format) { > + case OFORMAT_HUMAN: > + dump_human_image_info(info); > + dump_snapshots(bs); > + break; > + case OFORMAT_JSON: > + collect_snapshots(bs, info); > + dump_json_image_info(info); > + break; > + } > + > + g_free(filename); > + g_free(fmt); > + filename = NULL; > + fmt = NULL; > + > + if (chain) { > + if (info->has_full_backing_filename) { > + filename = g_strdup(info->full_backing_filename); > + } else if (info->has_backing_filename) { > + filename = g_strdup(info->backing_filename); > + } > + > + if (filename && info->has_backing_filename_format) { > + fmt = g_strdup(info->backing_filename_format); > + } > + > + /* Print delimiters between items */ > + if (filename) { > + switch (output_format) { > + case OFORMAT_HUMAN: > + printf("\n"); > + break; > + case OFORMAT_JSON: > + printf(",\n"); > + break; > + } > + } > + } > + > + qapi_free_ImageInfo(info); > + bdrv_delete(bs); > + } while (filename); > + > + if (chain && output_format == OFORMAT_JSON) { > + printf("]\n"); > + } > return 0; > + > +err: > + g_free(filename); > + g_free(fmt); > + return 1; > } > > #define SNAPSHOT_LIST 1 > -- > 1.7.11.4 > Thanks a lot Stefan for making this. Just tested this with latest qemu git. Works like a charm: [kashyap@moon qemu]$ ./qemu-img info --backing-chain /var/lib/libvirt/images/snap4-of-test-f17base.qcow2 image: /var/lib/libvirt/images/snap4-of-test-f17base.qcow2 file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: 3.6M cluster_size: 65536 backing file: /var/lib/libvirt/images/snap1-of-test-f17base.qcow2 backing file format: qcow2 image: /var/lib/libvirt/images/snap1-of-test-f17base.qcow2 file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: 968K cluster_size: 65536 backing file: /export/vmimgs2/test-f17base.img backing file format: raw image: /export/vmimgs2/test-f17base.img file format: raw virtual size: 1.0G (1073741824 bytes) disk size: 607M [kashyap@moon qemu]$
On Sat, Oct 13, 2012 at 12:46 AM, Kashyap Chamarthy <kashyap.cv@gmail.com> wrote: > On Fri, Oct 12, 2012 at 7:39 PM, Stefan Hajnoczi <stefanha@redhat.com> wrote: >> The qemu-img info --backing-chain option enumerates the backing file >> chain. For example, for base.qcow2 <- snap1.qcow2 <- snap2.qcow2 the >> output becomes: >> >> $ qemu-img info --backing-chain snap2.qcow2 >> image: snap2.qcow2 >> file format: qcow2 >> virtual size: 100M (104857600 bytes) >> disk size: 196K >> cluster_size: 65536 >> backing file: snap1.qcow2 >> backing file format: qcow2 >> >> image: snap1.qcow2 >> file format: qcow2 >> virtual size: 100M (104857600 bytes) >> disk size: 196K >> cluster_size: 65536 >> backing file: base.qcow2 >> backing file format: qcow2 >> >> image: base.qcow2 >> file format: qcow2 >> virtual size: 100M (104857600 bytes) >> disk size: 136K >> cluster_size: 65536 >> >> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >> --- >> qemu-img.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- >> 1 file changed, 76 insertions(+), 22 deletions(-) >> >> diff --git a/qemu-img.c b/qemu-img.c >> index f17f187..c717f3e 100644 >> --- a/qemu-img.c >> +++ b/qemu-img.c >> @@ -1249,7 +1249,10 @@ static void dump_human_image_info(ImageInfo *info) >> } >> } >> >> -enum {OPTION_OUTPUT = 256}; >> +enum { >> + OPTION_OUTPUT = 256, >> + OPTION_BACKING_CHAIN = 257, >> +}; >> >> typedef enum OutputFormat { >> OFORMAT_JSON, >> @@ -1260,7 +1263,9 @@ static int img_info(int argc, char **argv) >> { >> int c; >> OutputFormat output_format = OFORMAT_HUMAN; >> - const char *filename, *fmt, *output; >> + bool chain = false; >> + const char *output; >> + char *filename, *fmt; >> BlockDriverState *bs; >> ImageInfo *info; >> >> @@ -1272,6 +1277,7 @@ static int img_info(int argc, char **argv) >> {"help", no_argument, 0, 'h'}, >> {"format", required_argument, 0, 'f'}, >> {"output", required_argument, 0, OPTION_OUTPUT}, >> + {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, >> {0, 0, 0, 0} >> }; >> c = getopt_long(argc, argv, "f:h", >> @@ -1285,17 +1291,20 @@ static int img_info(int argc, char **argv) >> help(); >> break; >> case 'f': >> - fmt = optarg; >> + fmt = g_strdup(optarg); >> break; >> case OPTION_OUTPUT: >> output = optarg; >> break; >> + case OPTION_BACKING_CHAIN: >> + chain = true; >> + break; >> } >> } >> if (optind >= argc) { >> help(); >> } >> - filename = argv[optind++]; >> + filename = g_strdup(argv[optind++]); >> >> if (output && !strcmp(output, "json")) { >> output_format = OFORMAT_JSON; >> @@ -1303,31 +1312,76 @@ static int img_info(int argc, char **argv) >> output_format = OFORMAT_HUMAN; >> } else if (output) { >> error_report("--output must be used with human or json as argument."); >> - return 1; >> + goto err; >> } >> >> - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false); >> - if (!bs) { >> - return 1; >> + if (chain && output_format == OFORMAT_JSON) { >> + printf("[\n"); >> } >> >> - info = g_new0(ImageInfo, 1); >> - collect_image_info(bs, info, filename, fmt); >> + do { >> + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, >> + false); >> + if (!bs) { >> + goto err; >> + } >> >> - switch (output_format) { >> - case OFORMAT_HUMAN: >> - dump_human_image_info(info); >> - dump_snapshots(bs); >> - break; >> - case OFORMAT_JSON: >> - collect_snapshots(bs, info); >> - dump_json_image_info(info); >> - break; >> - } >> + info = g_new0(ImageInfo, 1); >> + collect_image_info(bs, info, filename, fmt); >> >> - qapi_free_ImageInfo(info); >> - bdrv_delete(bs); >> + switch (output_format) { >> + case OFORMAT_HUMAN: >> + dump_human_image_info(info); >> + dump_snapshots(bs); >> + break; >> + case OFORMAT_JSON: >> + collect_snapshots(bs, info); >> + dump_json_image_info(info); >> + break; >> + } >> + >> + g_free(filename); >> + g_free(fmt); >> + filename = NULL; >> + fmt = NULL; >> + >> + if (chain) { >> + if (info->has_full_backing_filename) { >> + filename = g_strdup(info->full_backing_filename); >> + } else if (info->has_backing_filename) { >> + filename = g_strdup(info->backing_filename); >> + } >> + >> + if (filename && info->has_backing_filename_format) { >> + fmt = g_strdup(info->backing_filename_format); >> + } >> + >> + /* Print delimiters between items */ >> + if (filename) { >> + switch (output_format) { >> + case OFORMAT_HUMAN: >> + printf("\n"); >> + break; >> + case OFORMAT_JSON: >> + printf(",\n"); >> + break; >> + } >> + } >> + } >> + >> + qapi_free_ImageInfo(info); >> + bdrv_delete(bs); >> + } while (filename); >> + >> + if (chain && output_format == OFORMAT_JSON) { >> + printf("]\n"); >> + } >> return 0; >> + >> +err: >> + g_free(filename); >> + g_free(fmt); >> + return 1; >> } >> >> #define SNAPSHOT_LIST 1 >> -- >> 1.7.11.4 >> > > Thanks a lot Stefan for making this. Just tested this with latest qemu > git. Works like a charm: > > [kashyap@moon qemu]$ ./qemu-img info --backing-chain > /var/lib/libvirt/images/snap4-of-test-f17base.qcow2 > image: /var/lib/libvirt/images/snap4-of-test-f17base.qcow2 > file format: qcow2 > virtual size: 1.0G (1073741824 bytes) > disk size: 3.6M > cluster_size: 65536 > backing file: /var/lib/libvirt/images/snap1-of-test-f17base.qcow2 > backing file format: qcow2 > > image: /var/lib/libvirt/images/snap1-of-test-f17base.qcow2 > file format: qcow2 > virtual size: 1.0G (1073741824 bytes) > disk size: 968K > cluster_size: 65536 > backing file: /export/vmimgs2/test-f17base.img > backing file format: raw > > image: /export/vmimgs2/test-f17base.img > file format: raw > virtual size: 1.0G (1073741824 bytes) > disk size: 607M > [kashyap@moon qemu]$ Attached a documentation patch for the '--backing-chain' option. /kashyap
On 10/12/2012 02:19 PM, Kashyap Chamarthy wrote: > > From eb4c4bc92c035c42c23c30c5e7ee73b54f9cf3a8 Mon Sep 17 00:00:00 2001 > From: Kashyap Chamarthy <kashyap.cv@gmail.com> > Date: Sat, 13 Oct 2012 01:30:37 +0530 > Subject: [PATCH] Add documentation for 'qemu-img info --backing-chain' > > Signed-off-by: Kashyap Chamarthy <kashyap.cv@gmail.com> > --- > qemu-img.texi | 19 ++++++++++++++++++- > 1 file changed, 18 insertions(+), 1 deletion(-) We also need a patch to qemu-img-cmds.hx. > @@ -129,7 +133,7 @@ created as a copy on write image of the specified base image; the > @var{backing_file} should have the same content as the input's base image, > however the path, image format, etc may differ. > > -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} > +@item info [-f @var{fmt}] [--output=@var{ofamt}] [--backing-chain] @var{filename} Introduced a spurious typo: s/ofamt/ofmt/ > > Give information about the disk image @var{filename}. Use it in > particular to know the size reserved on disk which can be different > @@ -137,6 +141,19 @@ from the displayed size. If VM snapshots are stored in the disk image, > they are displayed too. The command can output in the format @var{ofmt} > which is either @code{human} or @code{json}. > > +If a disk image has a backing file chain, information about each disk image in > +the chain can be recursively enumerated by using the option @code{--backing-chain} Trailing whitespace. Needs a '.' to end the sentence.
On Sat, Oct 13, 2012 at 2:01 AM, Eric Blake <eblake@redhat.com> wrote: > On 10/12/2012 02:19 PM, Kashyap Chamarthy wrote: > >> >> From eb4c4bc92c035c42c23c30c5e7ee73b54f9cf3a8 Mon Sep 17 00:00:00 2001 >> From: Kashyap Chamarthy <kashyap.cv@gmail.com> >> Date: Sat, 13 Oct 2012 01:30:37 +0530 >> Subject: [PATCH] Add documentation for 'qemu-img info --backing-chain' >> >> Signed-off-by: Kashyap Chamarthy <kashyap.cv@gmail.com> >> --- >> qemu-img.texi | 19 ++++++++++++++++++- >> 1 file changed, 18 insertions(+), 1 deletion(-) > > We also need a patch to qemu-img-cmds.hx. > >> @@ -129,7 +133,7 @@ created as a copy on write image of the specified base image; the >> @var{backing_file} should have the same content as the input's base image, >> however the path, image format, etc may differ. >> >> -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} >> +@item info [-f @var{fmt}] [--output=@var{ofamt}] [--backing-chain] @var{filename} > > Introduced a spurious typo: > s/ofamt/ofmt/ > >> >> Give information about the disk image @var{filename}. Use it in >> particular to know the size reserved on disk which can be different >> @@ -137,6 +141,19 @@ from the displayed size. If VM snapshots are stored in the disk image, >> they are displayed too. The command can output in the format @var{ofmt} >> which is either @code{human} or @code{json}. >> >> +If a disk image has a backing file chain, information about each disk image in >> +the chain can be recursively enumerated by using the option @code{--backing-chain} > > Trailing whitespace. Needs a '.' to end the sentence. Thanks for the review Eric, new patch attached. [PS: I haven't used 'git-send-email' for this trivial patch. Should I have used that, instead of attaching it? I was wondering if attachments like these are frowned upon. ] /kashyap > > -- > Eric Blake eblake@redhat.com +1-919-301-3266 > Libvirt virtualization library http://libvirt.org >
On 10/13/2012 09:50 AM, Kashyap Chamarthy wrote: > > [PS: I haven't used 'git-send-email' for this trivial patch. Should I > have used that, instead of attaching it? I was wondering if > attachments like these are frowned upon. ] That depends on who is applying the patch (it won't be me, since I'm not listed as maintainer); but even in my view as a reviewer, attachments embedded to a lengthy chain of reply text is harder to reply to than a fresh thread. So, given that I have review comments below, you might as well use 'git send-email' to post a v2 as a fresh thread, so we don't have to worry about whether this will be spotted deeply embedded in a thread. > From 68b22497ad1c9318ae57092f7e6af543b4106e1b Mon Sep 17 00:00:00 2001 > From: Kashyap Chamarthy <kashyap.cv@gmail.com> > Date: Sat, 13 Oct 2012 20:54:28 +0530 > Subject: [PATCH] Add documentation for 'qemu-img info --backing-chain' (with > Eric's comments fixed) The subject line becomes part of the permanent git history, and as such, it should avoid versioning information, and just describe the change (or in other words, leave my name out of the 'git log --one-line' output). Better would be: qemu-img: document 'info --backing-chain' > > Signed-off-by: Kashyap Chamarthy <kashyap.cv@gmail.com> > --- > qemu-img-cmds.hx | 4 ++-- > qemu-img.texi | 19 ++++++++++++++++++- > 2 files changed, 20 insertions(+), 3 deletions(-) > > > +@item --backing-chain > +will enumerate information about backing files in a disk image chain. Refer > +below for further description. > + > @item size > is the disk image size in bytes. Optional suffixes @code{k} or @code{K} > (kilobyte, 1024) @code{M} (megabyte, 1024k) and @code{G} (gigabyte, 1024M) > @@ -129,7 +133,7 @@ created as a copy on write image of the specified base image; the > @var{backing_file} should have the same content as the input's base image, > however the path, image format, etc may differ. > > -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} > +@item info [-f @var{fmt}] [--output=@var{oft}] [--backing-chain] @var{filename} Last time, you added a spurious 'a'; this time, you accidentally nuked an 'm'. Please, leave @var{ofmt} untouched.
On Sun, Oct 14, 2012 at 3:06 AM, Eric Blake <eblake@redhat.com> wrote: > On 10/13/2012 09:50 AM, Kashyap Chamarthy wrote: > >> >> [PS: I haven't used 'git-send-email' for this trivial patch. Should I >> have used that, instead of attaching it? I was wondering if >> attachments like these are frowned upon. ] > > That depends on who is applying the patch (it won't be me, since I'm not > listed as maintainer); but even in my view as a reviewer, attachments > embedded to a lengthy chain of reply text is harder to reply to than a > fresh thread. So, given that I have review comments below, you might as > well use 'git send-email' to post a v2 as a fresh thread, so we don't > have to worry about whether this will be spotted deeply embedded in a > thread. Noted. > >> From 68b22497ad1c9318ae57092f7e6af543b4106e1b Mon Sep 17 00:00:00 2001 >> From: Kashyap Chamarthy <kashyap.cv@gmail.com> >> Date: Sat, 13 Oct 2012 20:54:28 +0530 >> Subject: [PATCH] Add documentation for 'qemu-img info --backing-chain' (with >> Eric's comments fixed) > > The subject line becomes part of the permanent git history, and as such, > it should avoid versioning information, and just describe the change (or > in other words, leave my name out of the 'git log --one-line' output). > Better would be: > > qemu-img: document 'info --backing-chain' Noted. > >> >> Signed-off-by: Kashyap Chamarthy <kashyap.cv@gmail.com> >> --- >> qemu-img-cmds.hx | 4 ++-- >> qemu-img.texi | 19 ++++++++++++++++++- >> 2 files changed, 20 insertions(+), 3 deletions(-) >> > >> >> +@item --backing-chain >> +will enumerate information about backing files in a disk image chain. Refer >> +below for further description. >> + >> @item size >> is the disk image size in bytes. Optional suffixes @code{k} or @code{K} >> (kilobyte, 1024) @code{M} (megabyte, 1024k) and @code{G} (gigabyte, 1024M) >> @@ -129,7 +133,7 @@ created as a copy on write image of the specified base image; the >> @var{backing_file} should have the same content as the input's base image, >> however the path, image format, etc may differ. >> >> -@item info [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} >> +@item info [-f @var{fmt}] [--output=@var{oft}] [--backing-chain] @var{filename} > > Last time, you added a spurious 'a'; this time, you accidentally nuked > an 'm'. Please, leave @var{ofmt} untouched. Sorry for the overlook, fixed and sent a new one as a fresh thread. /kashyap > > -- > Eric Blake eblake@redhat.com +1-919-301-3266 > Libvirt virtualization library http://libvirt.org >
diff --git a/qemu-img.c b/qemu-img.c index f17f187..c717f3e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1249,7 +1249,10 @@ static void dump_human_image_info(ImageInfo *info) } } -enum {OPTION_OUTPUT = 256}; +enum { + OPTION_OUTPUT = 256, + OPTION_BACKING_CHAIN = 257, +}; typedef enum OutputFormat { OFORMAT_JSON, @@ -1260,7 +1263,9 @@ static int img_info(int argc, char **argv) { int c; OutputFormat output_format = OFORMAT_HUMAN; - const char *filename, *fmt, *output; + bool chain = false; + const char *output; + char *filename, *fmt; BlockDriverState *bs; ImageInfo *info; @@ -1272,6 +1277,7 @@ static int img_info(int argc, char **argv) {"help", no_argument, 0, 'h'}, {"format", required_argument, 0, 'f'}, {"output", required_argument, 0, OPTION_OUTPUT}, + {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "f:h", @@ -1285,17 +1291,20 @@ static int img_info(int argc, char **argv) help(); break; case 'f': - fmt = optarg; + fmt = g_strdup(optarg); break; case OPTION_OUTPUT: output = optarg; break; + case OPTION_BACKING_CHAIN: + chain = true; + break; } } if (optind >= argc) { help(); } - filename = argv[optind++]; + filename = g_strdup(argv[optind++]); if (output && !strcmp(output, "json")) { output_format = OFORMAT_JSON; @@ -1303,31 +1312,76 @@ static int img_info(int argc, char **argv) output_format = OFORMAT_HUMAN; } else if (output) { error_report("--output must be used with human or json as argument."); - return 1; + goto err; } - bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, false); - if (!bs) { - return 1; + if (chain && output_format == OFORMAT_JSON) { + printf("[\n"); } - info = g_new0(ImageInfo, 1); - collect_image_info(bs, info, filename, fmt); + do { + bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING, + false); + if (!bs) { + goto err; + } - switch (output_format) { - case OFORMAT_HUMAN: - dump_human_image_info(info); - dump_snapshots(bs); - break; - case OFORMAT_JSON: - collect_snapshots(bs, info); - dump_json_image_info(info); - break; - } + info = g_new0(ImageInfo, 1); + collect_image_info(bs, info, filename, fmt); - qapi_free_ImageInfo(info); - bdrv_delete(bs); + switch (output_format) { + case OFORMAT_HUMAN: + dump_human_image_info(info); + dump_snapshots(bs); + break; + case OFORMAT_JSON: + collect_snapshots(bs, info); + dump_json_image_info(info); + break; + } + + g_free(filename); + g_free(fmt); + filename = NULL; + fmt = NULL; + + if (chain) { + if (info->has_full_backing_filename) { + filename = g_strdup(info->full_backing_filename); + } else if (info->has_backing_filename) { + filename = g_strdup(info->backing_filename); + } + + if (filename && info->has_backing_filename_format) { + fmt = g_strdup(info->backing_filename_format); + } + + /* Print delimiters between items */ + if (filename) { + switch (output_format) { + case OFORMAT_HUMAN: + printf("\n"); + break; + case OFORMAT_JSON: + printf(",\n"); + break; + } + } + } + + qapi_free_ImageInfo(info); + bdrv_delete(bs); + } while (filename); + + if (chain && output_format == OFORMAT_JSON) { + printf("]\n"); + } return 0; + +err: + g_free(filename); + g_free(fmt); + return 1; } #define SNAPSHOT_LIST 1
The qemu-img info --backing-chain option enumerates the backing file chain. For example, for base.qcow2 <- snap1.qcow2 <- snap2.qcow2 the output becomes: $ qemu-img info --backing-chain snap2.qcow2 image: snap2.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 196K cluster_size: 65536 backing file: snap1.qcow2 backing file format: qcow2 image: snap1.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 196K cluster_size: 65536 backing file: base.qcow2 backing file format: qcow2 image: base.qcow2 file format: qcow2 virtual size: 100M (104857600 bytes) disk size: 136K cluster_size: 65536 Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- qemu-img.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 22 deletions(-)