|
|
9ae3a8 |
From 330cc46279f2fcd6f2d41d4e8beda8038c7a2fd9 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Date: Thu, 7 Nov 2013 13:18:21 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 87/87] vmdk: Implment bdrv_get_specific_info
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Message-id: <1383756824-6921-22-git-send-email-mreitz@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 55576
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 21/21] vmdk: Implment bdrv_get_specific_info
|
|
|
9ae3a8 |
Bugzilla: 980771
|
|
|
9ae3a8 |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
From: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
BZ: 980771
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Implement .bdrv_get_specific_info to return the extent information.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit f4c129a38a5430b7342a7a23f53a22831154612f)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
block/vmdk.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
|
|
|
9ae3a8 |
qapi-schema.json | 24 +++++++++++++++-
|
|
|
9ae3a8 |
tests/qemu-iotests/059 | 2 +-
|
|
|
9ae3a8 |
tests/qemu-iotests/059.out | 5 +--
|
|
|
9ae3a8 |
4 files changed, 93 insertions(+), 6 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/block/vmdk.c b/block/vmdk.c
|
|
|
9ae3a8 |
index 8bef9f2..a3267fe 100644
|
|
|
9ae3a8 |
--- a/block/vmdk.c
|
|
|
9ae3a8 |
+++ b/block/vmdk.c
|
|
|
9ae3a8 |
@@ -106,6 +106,7 @@ typedef struct VmdkExtent {
|
|
|
9ae3a8 |
uint32_t l2_cache_counts[L2_CACHE_SIZE];
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
int64_t cluster_sectors;
|
|
|
9ae3a8 |
+ char *type;
|
|
|
9ae3a8 |
} VmdkExtent;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
typedef struct BDRVVmdkState {
|
|
|
9ae3a8 |
@@ -113,11 +114,13 @@ typedef struct BDRVVmdkState {
|
|
|
9ae3a8 |
uint64_t desc_offset;
|
|
|
9ae3a8 |
bool cid_updated;
|
|
|
9ae3a8 |
bool cid_checked;
|
|
|
9ae3a8 |
+ uint32_t cid;
|
|
|
9ae3a8 |
uint32_t parent_cid;
|
|
|
9ae3a8 |
int num_extents;
|
|
|
9ae3a8 |
/* Extent array with num_extents entries, ascend ordered by address */
|
|
|
9ae3a8 |
VmdkExtent *extents;
|
|
|
9ae3a8 |
Error *migration_blocker;
|
|
|
9ae3a8 |
+ char *create_type;
|
|
|
9ae3a8 |
} BDRVVmdkState;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
typedef struct VmdkMetaData {
|
|
|
9ae3a8 |
@@ -214,6 +217,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
|
|
|
9ae3a8 |
g_free(e->l1_table);
|
|
|
9ae3a8 |
g_free(e->l2_cache);
|
|
|
9ae3a8 |
g_free(e->l1_backup_table);
|
|
|
9ae3a8 |
+ g_free(e->type);
|
|
|
9ae3a8 |
if (e->file != bs->file) {
|
|
|
9ae3a8 |
bdrv_delete(e->file);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -534,6 +538,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|
|
9ae3a8 |
uint32_t l1_size, l1_entry_sectors;
|
|
|
9ae3a8 |
VMDK4Header header;
|
|
|
9ae3a8 |
VmdkExtent *extent;
|
|
|
9ae3a8 |
+ BDRVVmdkState *s = bs->opaque;
|
|
|
9ae3a8 |
int64_t l1_backup_offset = 0;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
|
|
|
9ae3a8 |
@@ -549,6 +554,10 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+ if (!s->create_type) {
|
|
|
9ae3a8 |
+ s->create_type = g_strdup("monolithicSparse");
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) {
|
|
|
9ae3a8 |
/*
|
|
|
9ae3a8 |
* The footer takes precedence over the header, so read it in. The
|
|
|
9ae3a8 |
@@ -709,6 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|
|
9ae3a8 |
int64_t flat_offset;
|
|
|
9ae3a8 |
char extent_path[PATH_MAX];
|
|
|
9ae3a8 |
BlockDriverState *extent_file;
|
|
|
9ae3a8 |
+ BDRVVmdkState *s = bs->opaque;
|
|
|
9ae3a8 |
+ VmdkExtent *extent;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
while (*p) {
|
|
|
9ae3a8 |
/* parse extent line:
|
|
|
9ae3a8 |
@@ -749,7 +760,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|
|
9ae3a8 |
/* save to extents array */
|
|
|
9ae3a8 |
if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {
|
|
|
9ae3a8 |
/* FLAT extent */
|
|
|
9ae3a8 |
- VmdkExtent *extent;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
ret = vmdk_add_extent(bs, extent_file, true, sectors,
|
|
|
9ae3a8 |
0, 0, 0, 0, 0, &extent, errp);
|
|
|
9ae3a8 |
@@ -764,10 +774,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|
|
9ae3a8 |
bdrv_delete(extent_file);
|
|
|
9ae3a8 |
return ret;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ extent = &s->extents[s->num_extents - 1];
|
|
|
9ae3a8 |
} else {
|
|
|
9ae3a8 |
error_setg(errp, "Unsupported extent type '%s'", type);
|
|
|
9ae3a8 |
return -ENOTSUP;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ extent->type = g_strdup(type);
|
|
|
9ae3a8 |
next_line:
|
|
|
9ae3a8 |
/* move to next line */
|
|
|
9ae3a8 |
while (*p && *p != '\n') {
|
|
|
9ae3a8 |
@@ -812,6 +824,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
|
|
|
9ae3a8 |
ret = -ENOTSUP;
|
|
|
9ae3a8 |
goto exit;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ s->create_type = g_strdup(ct);
|
|
|
9ae3a8 |
s->desc_offset = 0;
|
|
|
9ae3a8 |
ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp);
|
|
|
9ae3a8 |
exit:
|
|
|
9ae3a8 |
@@ -838,6 +851,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
if (ret) {
|
|
|
9ae3a8 |
goto fail;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ s->cid = vmdk_read_cid(bs, 0);
|
|
|
9ae3a8 |
s->parent_cid = vmdk_read_cid(bs, 1);
|
|
|
9ae3a8 |
qemu_co_mutex_init(&s->lock);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
@@ -850,6 +864,8 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
|
|
|
9ae3a8 |
return 0;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
fail:
|
|
|
9ae3a8 |
+ g_free(s->create_type);
|
|
|
9ae3a8 |
+ s->create_type = NULL;
|
|
|
9ae3a8 |
vmdk_free_extents(bs);
|
|
|
9ae3a8 |
return ret;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
@@ -1761,6 +1777,7 @@ static void vmdk_close(BlockDriverState *bs)
|
|
|
9ae3a8 |
BDRVVmdkState *s = bs->opaque;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
vmdk_free_extents(bs);
|
|
|
9ae3a8 |
+ g_free(s->create_type);
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
migrate_del_blocker(s->migration_blocker);
|
|
|
9ae3a8 |
error_free(s->migration_blocker);
|
|
|
9ae3a8 |
@@ -1822,6 +1839,54 @@ static int vmdk_has_zero_init(BlockDriverState *bs)
|
|
|
9ae3a8 |
return 1;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ ImageInfo *info = g_new0(ImageInfo, 1);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ *info = (ImageInfo){
|
|
|
9ae3a8 |
+ .filename = g_strdup(extent->file->filename),
|
|
|
9ae3a8 |
+ .format = g_strdup(extent->type),
|
|
|
9ae3a8 |
+ .virtual_size = extent->sectors * BDRV_SECTOR_SIZE,
|
|
|
9ae3a8 |
+ .compressed = extent->compressed,
|
|
|
9ae3a8 |
+ .has_compressed = extent->compressed,
|
|
|
9ae3a8 |
+ .cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE,
|
|
|
9ae3a8 |
+ .has_cluster_size = !extent->flat,
|
|
|
9ae3a8 |
+ };
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ return info;
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ int i;
|
|
|
9ae3a8 |
+ BDRVVmdkState *s = bs->opaque;
|
|
|
9ae3a8 |
+ ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1);
|
|
|
9ae3a8 |
+ ImageInfoList **next;
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ *spec_info = (ImageInfoSpecific){
|
|
|
9ae3a8 |
+ .kind = IMAGE_INFO_SPECIFIC_KIND_VMDK,
|
|
|
9ae3a8 |
+ {
|
|
|
9ae3a8 |
+ .vmdk = g_new0(ImageInfoSpecificVmdk, 1),
|
|
|
9ae3a8 |
+ },
|
|
|
9ae3a8 |
+ };
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ *spec_info->vmdk = (ImageInfoSpecificVmdk) {
|
|
|
9ae3a8 |
+ .create_type = g_strdup(s->create_type),
|
|
|
9ae3a8 |
+ .cid = s->cid,
|
|
|
9ae3a8 |
+ .parent_cid = s->parent_cid,
|
|
|
9ae3a8 |
+ };
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ next = &spec_info->vmdk->extents;
|
|
|
9ae3a8 |
+ for (i = 0; i < s->num_extents; i++) {
|
|
|
9ae3a8 |
+ *next = g_new0(ImageInfoList, 1);
|
|
|
9ae3a8 |
+ (*next)->value = vmdk_get_extent_info(&s->extents[i]);
|
|
|
9ae3a8 |
+ (*next)->next = NULL;
|
|
|
9ae3a8 |
+ next = &(*next)->next;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ return spec_info;
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static QEMUOptionParameter vmdk_create_options[] = {
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
.name = BLOCK_OPT_SIZE,
|
|
|
9ae3a8 |
@@ -1874,6 +1939,7 @@ static BlockDriver bdrv_vmdk = {
|
|
|
9ae3a8 |
.bdrv_co_get_block_status = vmdk_co_get_block_status,
|
|
|
9ae3a8 |
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
|
|
|
9ae3a8 |
.bdrv_has_zero_init = vmdk_has_zero_init,
|
|
|
9ae3a8 |
+ .bdrv_get_specific_info = vmdk_get_specific_info,
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
.create_options = vmdk_create_options,
|
|
|
9ae3a8 |
};
|
|
|
9ae3a8 |
diff --git a/qapi-schema.json b/qapi-schema.json
|
|
|
9ae3a8 |
index 99b05b7..64696a9 100644
|
|
|
9ae3a8 |
--- a/qapi-schema.json
|
|
|
9ae3a8 |
+++ b/qapi-schema.json
|
|
|
9ae3a8 |
@@ -225,6 +225,27 @@
|
|
|
9ae3a8 |
} }
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
+# @ImageInfoSpecificVmdk:
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# @create_type: The create type of VMDK image
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# @cid: Content id of image
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# @parent-cid: Parent VMDK image's cid
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# @extents: List of extent files
|
|
|
9ae3a8 |
+#
|
|
|
9ae3a8 |
+# Since: 1.7
|
|
|
9ae3a8 |
+##
|
|
|
9ae3a8 |
+{ 'type': 'ImageInfoSpecificVmdk',
|
|
|
9ae3a8 |
+ 'data': {
|
|
|
9ae3a8 |
+ 'create-type': 'str',
|
|
|
9ae3a8 |
+ 'cid': 'int',
|
|
|
9ae3a8 |
+ 'parent-cid': 'int',
|
|
|
9ae3a8 |
+ 'extents': ['ImageInfo']
|
|
|
9ae3a8 |
+ } }
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+##
|
|
|
9ae3a8 |
# @ImageInfoSpecific:
|
|
|
9ae3a8 |
#
|
|
|
9ae3a8 |
# A discriminated record of image format specific information structures.
|
|
|
9ae3a8 |
@@ -234,7 +255,8 @@
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
{ 'union': 'ImageInfoSpecific',
|
|
|
9ae3a8 |
'data': {
|
|
|
9ae3a8 |
- 'qcow2': 'ImageInfoSpecificQCow2'
|
|
|
9ae3a8 |
+ 'qcow2': 'ImageInfoSpecificQCow2',
|
|
|
9ae3a8 |
+ 'vmdk': 'ImageInfoSpecificVmdk'
|
|
|
9ae3a8 |
} }
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
##
|
|
|
9ae3a8 |
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
|
|
|
9ae3a8 |
index 26d4538..36103e1 100755
|
|
|
9ae3a8 |
--- a/tests/qemu-iotests/059
|
|
|
9ae3a8 |
+++ b/tests/qemu-iotests/059
|
|
|
9ae3a8 |
@@ -69,7 +69,7 @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
|
|
|
9ae3a8 |
echo "=== Testing monolithicFlat creation and opening ==="
|
|
|
9ae3a8 |
echo
|
|
|
9ae3a8 |
IMGOPTS="subformat=monolithicFlat" _make_test_img 2G
|
|
|
9ae3a8 |
-$QEMU_IMG info $TEST_IMG | _filter_testdir
|
|
|
9ae3a8 |
+_img_info
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
echo
|
|
|
9ae3a8 |
echo "=== Testing monolithicFlat with zeroed_grain ==="
|
|
|
9ae3a8 |
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
|
|
|
9ae3a8 |
index 2b29ca9..5829794 100644
|
|
|
9ae3a8 |
--- a/tests/qemu-iotests/059.out
|
|
|
9ae3a8 |
+++ b/tests/qemu-iotests/059.out
|
|
|
9ae3a8 |
@@ -18,10 +18,9 @@ no file open, try 'help open'
|
|
|
9ae3a8 |
=== Testing monolithicFlat creation and opening ===
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
|
|
|
9ae3a8 |
-image: TEST_DIR/t.vmdk
|
|
|
9ae3a8 |
-file format: vmdk
|
|
|
9ae3a8 |
+image: TEST_DIR/t.IMGFMT
|
|
|
9ae3a8 |
+file format: IMGFMT
|
|
|
9ae3a8 |
virtual size: 2.0G (2147483648 bytes)
|
|
|
9ae3a8 |
-disk size: 4.0K
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
=== Testing monolithicFlat with zeroed_grain ===
|
|
|
9ae3a8 |
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|