The `qemu-img info` results for mono flat image are no longer
accurate, as the "disk size" was the length of bs->file, which is not
the case for multi file images (such as vmdk images with multiple
files).
The new field disk_size in BlockDriverState can be used by block
driver to tell the exact disk size of block image (only valid if the
field is set to non-zero).

Signed-off-by: Fam Zheng <famc...@gmail.com>
---
 block/vmdk.c |    1 +
 block_int.h  |    1 +
 qemu-img.c   |    6 +++++-
 3 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 43b47e2..39c553c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -607,6 +607,7 @@ static int vmdk_open_desc_file(BlockDriverState
*bs, int flags)
     extent = s->extents;
     vmdk_parse_extents(buf, s->extents, bs->file->filename);
     bs->total_sectors = extent->sectors;
+    bs->disk_size = bdrv_getlength(bs->file) + bdrv_getlength(extent->file);

     // try to open parent images, if exist
     if (vmdk_parent_open(bs) != 0) {
diff --git a/block_int.h b/block_int.h
index dd8f8cb..4c58d6d 100644
--- a/block_int.h
+++ b/block_int.h
@@ -144,6 +144,7 @@ struct BlockDriver {
 struct BlockDriverState {
     int64_t total_sectors; /* if we are reading a disk image, give its
                               size in sectors */
+    int64_t disk_size; /* if non-zero, holds the disk size of image */
     int read_only; /* if true, the media is read only */
     int keep_read_only; /* if true, the media was requested to stay
read only */
     int open_flags; /* flags used to open the file, re-used for re-open */
diff --git a/qemu-img.c b/qemu-img.c
index 4f162d1..7ea8faf 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1067,7 +1067,11 @@ static int img_info(int argc, char **argv)
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
-    allocated_size = get_allocated_file_size(filename);
+    if (bs->disk_size) {
+        allocated_size = bs->disk_size;
+    } else {
+        allocated_size = get_allocated_file_size(filename);
+    }
     if (allocated_size < 0) {
         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
     } else {

Reply via email to