On Sat, Oct 13, 2012 at 12:46 AM, Kashyap Chamarthy <kashyap...@gmail.com> wrote: > 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]$
Attached a documentation patch for the '--backing-chain' option. /kashyap
0001-Add-documentation-for-qemu-img-info-backing-chain.patch
Description: Binary data