On Fri, Oct 12, 2012 at 7:39 PM, Stefan Hajnoczi <stefa...@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 <stefa...@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]$