vmdk: Implement blockdev-create
v4 cover vmdk: Implement blockdev-create
I picked up the patch series from Fam and rebased it to current master (which involved a major rework on the test case) and tried to address Markus' review comments for v2. I did not do any further review of the actual code, but it passes the tests, so I guess having it in tree is better than continuing to let it bitrot.
v4:
- Use "legacyESX" in QAPI instead of "legacyesx" (requires an additional exception from the QAPI rules, but the string is directly written into the VMDK file, and "legacyESX" is the spelling in the spec). The QemuOpts based parser stays case sensitive in v4. [Markus]
- Documentation fixes [Markus]
- Added tests for adapter types
- Added patch 5 to forbid excess extents in blockdev-create [Markus]
Fam Zheng (3):
vmdk: Refactor vmdk_create_extent
vmdk: Implement .bdrv_co_create callback
iotests: Filter cid numbers in VMDK extent info
Kevin Wolf (2):
iotests: Add VMDK tests for blockdev-create
vmdk: Reject excess extents in blockdev-create
qapi/block-core.json | 71 +++++ qapi/qapi-schema.json | 16 +- block/vmdk.c | 532 ++++++++++++++++++++++--------- tests/qemu-iotests/237 | 237 ++++++++++++++ tests/qemu-iotests/237.out | 348 ++++++++++++++++++++ tests/qemu-iotests/common.filter | 1 + tests/qemu-iotests/group | 1 + tests/qemu-iotests/iotests.py | 1 + 8 files changed, 1049 insertions(+), 158 deletions(-) create mode 100755 tests/qemu-iotests/237 create mode 100644 tests/qemu-iotests/237.out
Signature · 1 line
2.19.2
PATCH v4 1/5 vmdk: Refactor vmdk_create_extent
From: Fam Zheng <[email protected]>
The extracted vmdk_init_extent takes a BlockBackend object and initializes the format metadata. It is the common part between "qemu-img create" and "blockdev-create".
Add a "BlockBackend *pbb" parameter to vmdk_create_extent, to return the opened BB to the caller in the next patch.
--- block/vmdk.c | 69 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 26 deletions(-)
block/vmdk.c +43 -26
@@ -1741,35 +1741,17 @@ static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,return ret; } -static int vmdk_create_extent (const char *filename,int64_t filesize, -bool flat,bool compress,bool zeroed_grain, -QemuOpts *opts,Error **errp) +static int vmdk_init_extent (BlockBackend *blk, +int64_t filesize,bool flat, +bool compress,bool zeroed_grain, +Error **errp) {int ret, i; -BlockBackend *blk =NULL ;VMDK4Header header; -Error *local_err =NULL ;uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count;uint32_t *gd_buf =NULL ;int gd_buf_size; - ret =bdrv_create_file (filename, opts, &local_err); -if (ret <0 ) { -error_propagate (errp, local_err); - goto exit; - } - - blk =blk_new_open (filename,NULL ,NULL , -BDRV_O_RDWR |BDRV_O_RESIZE |BDRV_O_PROTOCOL , - &local_err); -if (blk ==NULL ) { -error_propagate (errp, local_err); - ret = -EIO ; - goto exit; - } - -blk_set_allow_write_beyond_eof (blk, true); -if (flat) { ret =blk_truncate (blk, filesize,PREALLOC_MODE_OFF , errp); goto exit;
@@ -1863,15 +1845,50 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, gd_buf, gd_buf_size, 0);if (ret <0 ) {error_setg (errp,QERR_IO_ERROR ); - goto exit; } ret =0 ; +exit: +g_free (gd_buf); +return ret; +} + +static int vmdk_create_extent (const char *filename,int64_t filesize, +bool flat,bool compress,bool zeroed_grain, +BlockBackend **pbb, +QemuOpts *opts,Error **errp) +{ +int ret; +BlockBackend *blk =NULL ; +Error *local_err =NULL ; + + ret =bdrv_create_file (filename, opts, &local_err); +if (ret <0 ) { +error_propagate (errp, local_err); + goto exit; + } + + blk =blk_new_open (filename,NULL ,NULL , +BDRV_O_RDWR |BDRV_O_RESIZE |BDRV_O_PROTOCOL , + &local_err); +if (blk ==NULL ) { +error_propagate (errp, local_err); + ret = -EIO ; + goto exit; + } + +blk_set_allow_write_beyond_eof (blk, true); + + ret =vmdk_init_extent (blk, filesize, flat, compress, zeroed_grain, errp); exit:if (blk) { -blk_unref (blk); +if (pbb) { + *pbb = blk; + }else { +blk_unref (blk); + blk =NULL ; + } } -g_free (gd_buf);return ret; }
@@ -2094,7 +2111,7 @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *optssnprintf (ext_filename,PATH_MAX ,"%s%s" , path, desc_filename);if (vmdk_create_extent (ext_filename, size, - flat, compress, zeroed_grain, opts, errp)) { + flat, compress, zeroed_grain,NULL , opts, errp)) { ret = -EINVAL ; goto exit; }
Signature · 1 line
2.19.2
PATCH v4 2/5 vmdk: Implement .bdrv_co_create callback
In reply to Kevin WolfFrom: Fam Zheng <[email protected]>
This makes VMDK support blockdev-create. The implementation reuses the image creation code in vmdk_co_create_opts which now acceptes a callback pointer to "retrieve" BlockBackend pointers from the caller. This way we separate the logic between file/extent acquisition and initialization.
The QAPI command parameters are mostly the same as the old create_opts except the dropped legacy @compat6 switch, which is redundant with @hwversion.
--- qapi/block-core.json | 70 +++++++ qapi/qapi-schema.json | 16 +- block/vmdk.c | 448 ++++++++++++++++++++++++++++++------------ 3 files changed, 400 insertions(+), 134 deletions(-)
qapi/block-core.json +70 -0
@@ -4021,6 +4021,75 @@ 'size': 'size', '*cluster-size' : 'size' } } +## +# @BlockdevVmdkSubformat: +# +# Subformat options for VMDK images +# +# @monolithicSparse: Single file image with sparse cluster allocation +# +# @monolithicFlat: Single flat data image and a descriptor file +# +# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse extent +# files, in addition to a descriptor file +# +# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat extent +# files, in addition to a descriptor file +# +# @streamOptimized: Single file image sparse cluster allocation, optimized +# for streaming over network. +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkSubformat', + 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse', + 'twoGbMaxExtentFlat', 'streamOptimized'] } + +## +# @BlockdevVmdkAdapterType: +# +# Adapter type info for VMDK images +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkAdapterType', + 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] } + +## +# @BlockdevCreateOptionsVmdk: +# +# Driver specific image creation options for VMDK. +# +# @file Where to store the new image file. This refers to the image +# file for monolithcSparse and streamOptimized format, or the +# descriptor file for other formats. +# @size Size of the virtual disk in bytes +# @extents Where to store the data extents. Required for monolithcFlat, +# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For +# monolithicFlat, only one entry is required; for +# twoGbMaxExtent* formats, the number of entries required is +# calculated as extent_number = virtual_size / 2GB. +# @subformat The subformat of the VMDK image. Default: "monolithicSparse". +# @backing-file The path of backing file. Default: no backing file is used. +# @adapter-type The adapter type used to fill in the descriptor. Default: ide. +# @hwversion Hardware version. The meaningful options are "4" or "6". +# Default: "4". +# @zeroed-grain Whether to enable zeroed-grain feature for sparse subformats. +# Default: false. +# +# Since: 4.0 +## +{ 'struct': 'BlockdevCreateOptionsVmdk', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*extents': ['BlockdevRef'], + '*subformat': 'BlockdevVmdkSubformat', + '*backing-file': 'str', + '*adapter-type': 'BlockdevVmdkAdapterType', + '*hwversion': 'str', + '*zeroed-grain': 'bool' } } + + ## # @SheepdogRedundancyType: #
@@ -4215,6 +4284,7 @@ 'ssh': 'BlockdevCreateOptionsSsh', 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', + 'vmdk': 'BlockdevCreateOptionsVmdk', 'vpc': 'BlockdevCreateOptionsVpc' } }
qapi/qapi-schema.json +9 -7
@@ -63,13 +63,15 @@ 'query-tpm-types', 'ringbuf-read' ], 'name-case-whitelist': [ - 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status - 'CpuInfoMIPS', # PC, visible through query-cpu - 'CpuInfoTricore', # PC, visible through query-cpu - 'QapiErrorClass', # all members, visible through errors - 'UuidInfo', # UUID, visible through query-uuid - 'X86CPURegister32', # all members, visible indirectly through qom-get - 'q_obj_CpuInfo-base' # CPU, visible through query-cpu + 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status + 'CpuInfoMIPS', # PC, visible through query-cpu + 'CpuInfoTricore', # PC, visible through query-cpu + 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings + 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings + 'QapiErrorClass', # all members, visible through errors + 'UuidInfo', # UUID, visible through query-uuid + 'X86CPURegister32', # all members, visible indirectly through qom-get + 'q_obj_CpuInfo-base' # CPU, visible through query-cpu ] } } # Documentation generated with qapi-gen.py is in source order, with
block/vmdk.c +321 -127
554 lines not on this page · raw message
Signature · 1 line
2.19.2
Re: [Qemu-devel] [PATCH v4 2/5] vmdk: Implement .bdrv_co_create callback
Quoted 65 lines · Kevin Wolf
From: Fam Zheng <[email protected]>
This makes VMDK support blockdev-create. The implementation reuses the image creation code in
vmdk_co_create_optswhich now acceptes a callback pointer to "retrieve" BlockBackend pointers from the caller. This way we separate the logic between file/extent acquisition and initialization.The QAPI command parameters are mostly the same as the old
create_optsexcept the dropped legacy @compat6 switch, which is redundant with @hwversion.Signed-off-by Fam Zheng <[email protected]>Signed-off-by Kevin Wolf <[email protected]>--- qapi/block-core.json | 70 +++++++ qapi/qapi-schema.json | 16 +- block/vmdk.c | 448 ++++++++++++++++++++++++++++++------------ 3 files changed, 400 insertions(+), 134 deletions(-)qapi/block-core.json +38
-0@@ -4021,6 +4021,75 @@ 'size': 'size', '*cluster-size' : 'size' } } +## +# @BlockdevVmdkSubformat: +# +# Subformat options for VMDK images +# +# @monolithicSparse: Single file image with sparse cluster allocation +# +# @monolithicFlat: Single flat data image and a descriptor file +# +# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse extent +# files, in addition to a descriptor file +# +# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat extent +# files, in addition to a descriptor file +# +# @streamOptimized: Single file image sparse cluster allocation, optimized +# for streaming over network. +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkSubformat', + 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse', + 'twoGbMaxExtentFlat', 'streamOptimized'] } + +## +# @BlockdevVmdkAdapterType: +# +# Adapter type info for VMDK images +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkAdapterType', + 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] } + +## +# @BlockdevCreateOptionsVmdk: +# +# Driver specific image creation options for VMDK.
qapi/block-core.json line 4071
Quoted 10 lines
qapi/block-core.json +10
-0+# +# @file Where to store the new image file. This refers to the image +# file for monolithcSparse and streamOptimized format, or the +# descriptor file for other formats. +# @size Size of the virtual disk in bytes +# @extents Where to store the data extents. Required for monolithcFlat, +# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For +# monolithicFlat, only one entry is required; for +# twoGbMaxExtent* formats, the number of entries required is +# calculated as extent_number = virtual_size / 2GB.
Doesn't quite spell out that the number of extents has to match exactly. I'm not sure I care.
Quoted 32 lines
qapi/block-core.json +22
-0+# @subformat The subformat of the VMDK image. Default: "monolithicSparse". +# @backing-file The path of backing file. Default: no backing file is used. +# @adapter-type The adapter type used to fill in the descriptor. Default: ide. +# @hwversion Hardware version. The meaningful options are "4" or "6". +# Default: "4". +# @zeroed-grain Whether to enable zeroed-grain feature for sparse subformats. +# Default: false. +# +# Since: 4.0 +## +{ 'struct': 'BlockdevCreateOptionsVmdk', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*extents': ['BlockdevRef'], + '*subformat': 'BlockdevVmdkSubformat', + '*backing-file': 'str', + '*adapter-type': 'BlockdevVmdkAdapterType', + '*hwversion': 'str', + '*zeroed-grain': 'bool' } } + + ## # @SheepdogRedundancyType: #@@ -4215,6 +4284,7 @@ 'ssh': 'BlockdevCreateOptionsSsh', 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', + 'vmdk': 'BlockdevCreateOptionsVmdk', 'vpc': 'BlockdevCreateOptionsVpc' } }
[...]
Re: [Qemu-devel] [PATCH v4 2/5] vmdk: Implement .bdrv_co_create callback
Quoted 25 lines · Markus Armbruster
Quoted 23 lines · Kevin Wolf
From: Fam Zheng <[email protected]>
This makes VMDK support blockdev-create. The implementation reuses the image creation code in
vmdk_co_create_optswhich now acceptes a callback pointer to "retrieve" BlockBackend pointers from the caller. This way we separate the logic between file/extent acquisition and initialization.The QAPI command parameters are mostly the same as the old
create_optsexcept the dropped legacy @compat6 switch, which is redundant with @hwversion.Signed-off-by Fam Zheng <[email protected]>Signed-off-by Kevin Wolf <[email protected]>--- qapi/block-core.json | 70 +++++++ qapi/qapi-schema.json | 16 +- block/vmdk.c | 448 ++++++++++++++++++++++++++++++------------ 3 files changed, 400 insertions(+), 134 deletions(-)qapi/block-core.json +0
-0
[...]
Quoted 9 lines
Quoted 9 lines
qapi/block-core.json +9
-0+## +# @BlockdevCreateOptionsVmdk: +# +# Driver specific image creation options for VMDK. +# +# @file Where to store the new image file. This refers to the image +# file for monolithcSparse and streamOptimized format, or the +# descriptor file for other formats. +# @size Size of the virtual disk in bytes
Quoted 8 lines
qapi/block-core.json line 4071
Quoted 5 lines
qapi/block-core.json +5
-0+# @extents Where to store the data extents. Required for monolithcFlat, +# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For +# monolithicFlat, only one entry is required; for +# twoGbMaxExtent* formats, the number of entries required is +# calculated as extent_number = virtual_size / 2GB.Doesn't quite spell out that the number of extents has to match exactly. I'm not sure I care.
Nevermind, you address that in PATCH 5.
[...]
PATCH v4 3/5 iotests: Filter cid numbers in VMDK extent info
In reply to Kevin WolfFrom: Fam Zheng <[email protected]>
--- tests/qemu-iotests/common.filter | 1 + tests/qemu-iotests/iotests.py | 1 + 2 files changed, 2 insertions(+)
tests/qemu-iotests/common.filter +1 -0
@@ -165,6 +165,7 @@ _filter_img_info() -e "/table_size: [0-9]\\+/d" \ -e "/compat: '[^']*'/d" \ -e "/compat6: \\(on\\|off\\)/d" \ + -e "s/cid: [0-9]\+/cid: XXXXXXXXXX/" \ -e "/static: \\(on\\|off\\)/d" \ -e "/zeroed_grain: \\(on\\|off\\)/d" \ -e "/subformat: '[^']*'/d" \
tests/qemu-iotests/iotests.py +1 -0
@@ -248,6 +248,7 @@ def filter_img_info(output, filename): .replace(imgfmt, 'IMGFMT') line = re.sub('iters: [0-9]+', 'iters: XXX', line) line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line) + line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line) lines.append(line) return '\n'.join(lines)
Signature · 1 line
2.19.2
PATCH v4 4/5 iotests: Add VMDK tests for blockdev-create
In reply to Kevin Wolf--- tests/qemu-iotests/237 | 233 +++++++++++++++++++++++++ tests/qemu-iotests/237.out | 347 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 581 insertions(+) create mode 100755 tests/qemu-iotests/237 create mode 100644 tests/qemu-iotests/237.out
tests/qemu-iotests/237 new file +233 -0
@@ -0,0 +1,233 @@ +#!/usr/bin/env python +# +# Test vmdk and file image creation +# +# Copyright (C) 2018 Red Hat, Inc. +# +# Creator/Owner: Kevin Wolf <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['vmdk']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.vmdk') as disk_path, \ + iotests.FilePath('t.vmdk.1') as extent1_path, \ + iotests.FilePath('t.vmdk.2') as extent2_path, \ + iotests.FilePath('t.vmdk.3') as extent3_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 5 * 1024 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (inline blockdev-add, explicit defaults) + # + iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'ide', + 'hwversion': '4', + 'zeroed-grain': False }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'buslogic', + 'zeroed-grain': True }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Adapter types + # + + iotests.log("=== Adapter types ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + + # Valid + iotests.log("== Valid adapter types ==") + iotests.log("") + + vm.launch() + for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() + + # Invalid + iotests.log("== Invalid adapter types ==") + iotests.log("") + + vm.launch() + for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() + + # + # Other subformats + # + iotests.log("=== Other subformats ===") + iotests.log("") + + for path in [ extent1_path, extent2_path, extent3_path ]: + msg = iotests.qemu_img_pipe('create', '-f', imgfmt, path, '0') + iotests.log(msg, [iotests.filter_testfiles]) + + vm.add_blockdev('driver=file,filename=%s,node-name=ext1' % (extent1_path)) + vm.add_blockdev('driver=file,filename=%s,node-name=ext2' % (extent2_path)) + vm.add_blockdev('driver=file,filename=%s,node-name=ext3' % (extent3_path)) + + # Missing extent + iotests.log("== Missing extent ==") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat' }) + vm.shutdown() + + # Correct extent + iotests.log("== Correct extent ==") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat', + 'extents': ['ext1'] }) + vm.shutdown() + + # Extra extent + iotests.log("== Extra extent ==") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 512, + 'subformat': 'monolithicFlat', + 'extents': ['ext1', 'ext2', 'ext3'] }) + vm.shutdown() + + # Split formats + iotests.log("== Split formats ==") + iotests.log("") + + for size in [ 512, 1073741824, 2147483648, 5368709120 ]: + for subfmt in [ 'twoGbMaxExtentFlat', 'twoGbMaxExtentSparse' ]: + iotests.log("= %s %d =" % (subfmt, size)) + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': subfmt, + 'extents': ['ext1', 'ext2', 'ext3'] }) + vm.shutdown() + + iotests.img_info_log(disk_path)
tests/qemu-iotests/237.out new file +347 -0
347 lines not on this page · raw message
tests/qemu-iotests/group +1 -0
@@ -233,3 +233,4 @@ 233 auto quick 234 auto quick migration 235 auto quick +237 rw auto quick
Signature · 1 line
2.19.2
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Quoted 182 lines · Kevin Wolf
Signed-off-by Fam Zheng <[email protected]>Signed-off-by Kevin Wolf <[email protected]>--- tests/qemu-iotests/237 | 233 +++++++++++++++++++++++++ tests/qemu-iotests/237.out | 347 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 581 insertions(+) create mode 100755 tests/qemu-iotests/237 create mode 100644 tests/qemu-iotests/237.outtests/qemu-iotests/237 new file +166
-0@@ -0,0 +1,233 @@ +#!/usr/bin/env python +# +# Test vmdk and file image creation +# +# Copyright (C) 2018 Red Hat, Inc. +# +# Creator/Owner: Kevin Wolf <[email protected]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['vmdk']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.vmdk') as disk_path, \ + iotests.FilePath('t.vmdk.1') as extent1_path, \ + iotests.FilePath('t.vmdk.2') as extent2_path, \ + iotests.FilePath('t.vmdk.3') as extent3_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 5 * 1024 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (inline blockdev-add, explicit defaults) + # + iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'ide', + 'hwversion': '4', + 'zeroed-grain': False }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'buslogic', + 'zeroed-grain': True }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Adapter types + # + + iotests.log("=== Adapter types ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + + # Valid + iotests.log("== Valid adapter types ==") + iotests.log("") + + vm.launch() + for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() + + # Invalid + iotests.log("== Invalid adapter types ==") + iotests.log("") + + vm.launch() + for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() +
tests/qemu-iotests/237 line 176
Quoted 10 lines
tests/qemu-iotests/237 new file +10
-0+ # + # Other subformats + # + iotests.log("=== Other subformats ===") + iotests.log("") + + for path in [ extent1_path, extent2_path, extent3_path ]: + msg = iotests.qemu_img_pipe('create', '-f', imgfmt, path, '0') + iotests.log(msg, [iotests.filter_testfiles]) +
You lost
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
here since v3. Intentional?
Quoted 3 lines
tests/qemu-iotests/237 new file +3
-0+ vm.add_blockdev('driver=file,filename=%s,node-name=ext1' % (extent1_path)) + vm.add_blockdev('driver=file,filename=%s,node-name=ext2' % (extent2_path)) + vm.add_blockdev('driver=file,filename=%s,node-name=ext3' % (extent3_path))
[...]
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
In reply to Kevin Wolfgit-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Am 07.12.2018 um 14:12 hat Markus Armbruster geschrieben:
Quoted 12 lines
git-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.
This is in the reference output, so trailing whitespace/blank lines are actually correct.
Kevin
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Quoted 14 lines · Kevin Wolf
Am 07.12.2018 um 14:12 hat Markus Armbruster geschrieben:
Quoted 12 lines
git-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.
Quoted 2 lines
This is in the reference output, so trailing whitespace/blank lines are actually correct.
Ah, but doesn't ./check already ignore differences in trailing whitespace present in the actual running that is not present in the *.out files, precisely so we don't have to check in trailing whitespace reference outputs?
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Am 07.12.2018 um 16:40 hat Eric Blake geschrieben:
Quoted 15 lines · Kevin Wolf
Quoted 14 lines
Am 07.12.2018 um 14:12 hat Markus Armbruster geschrieben:
Quoted 12 lines
git-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.
Quoted 7 lines
Quoted 2 lines
This is in the reference output, so trailing whitespace/blank lines are actually correct.
Ah, but doesn't ./check already ignore differences in trailing whitespace present in the actual running that is not present in the *.out files, precisely so we don't have to check in trailing whitespace reference outputs?
It does ignore whitespace changes, so even if we remove that whitespace, the test won't fail. But I don't think that's a good reason to check in inaccurate reference output.
There are a few test cases that have a reference output like this and it's always annoying: When I later add a new subtest, I add the new test code, review the ./check output and if it looks good, I do something like 'cp 237.out.bad 237.out'. At that point, I'll have to manually revert completely unrelated whitespace changes again.
Some 'git am' warnings feel like the lesser evil to me.
Kevin
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Quoted 28 lines · Kevin Wolf
Am 07.12.2018 um 16:40 hat Eric Blake geschrieben:
Quoted 15 lines · Kevin Wolf
Quoted 14 lines
Am 07.12.2018 um 14:12 hat Markus Armbruster geschrieben:
Quoted 12 lines
git-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.Quoted 7 lines
Quoted 2 lines
This is in the reference output, so trailing whitespace/blank lines are actually correct.
Ah, but doesn't ./check already ignore differences in trailing whitespace present in the actual running that is not present in the *.out files, precisely so we don't have to check in trailing whitespace reference outputs?
It does ignore whitespace changes, so even if we remove that whitespace, the test won't fail. But I don't think that's a good reason to check in inaccurate reference output.
Quoted 5 lines
There are a few test cases that have a reference output like this and it's always annoying: When I later add a new subtest, I add the new test code, review the ./check output and if it looks good, I do something like 'cp 237.out.bad 237.out'. At that point, I'll have to manually revert completely unrelated whitespace changes again.
Is it worth teaching iotests.img_info_log() to strip trailing whitespace? Or even to teach qemu-img itself to quit generating trailing whitespace?
Quoted 2 lines
Some 'git am' warnings feel like the lesser evil to me.
True, and a comment in the commit message about intentionally triggering a known checkpatch flag goes a long ways to document why you want the trailing whitespace (assuming we don't instead decide to tackle a root cause of having the whitespace in the first place).
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH v4 4/5] iotests: Add VMDK tests for blockdev-create
Am 07.12.2018 um 17:52 hat Eric Blake geschrieben:
Quoted 29 lines · Kevin Wolf
Quoted 28 lines
Am 07.12.2018 um 16:40 hat Eric Blake geschrieben:
Quoted 15 lines · Kevin Wolf
Quoted 14 lines
Am 07.12.2018 um 14:12 hat Markus Armbruster geschrieben:
Quoted 12 lines
git-am complains
Applying: iotests: Add VMDK tests for blockdev-create .git/rebase-apply/patch:281: trailing whitespace.
format:
.git/rebase-apply/patch:308: trailing whitespace.
format:
.git/rebase-apply/patch:335: trailing whitespace.
format:
.git/rebase-apply/patch:600: new blank line at EOF. +
warning: 4 lines add whitespace errors.Quoted 7 lines
Quoted 2 lines
This is in the reference output, so trailing whitespace/blank lines are actually correct.
Ah, but doesn't ./check already ignore differences in trailing whitespace present in the actual running that is not present in the *.out files, precisely so we don't have to check in trailing whitespace reference outputs?
It does ignore whitespace changes, so even if we remove that whitespace, the test won't fail. But I don't think that's a good reason to check in inaccurate reference output.
Quoted 8 lines
Quoted 5 lines
There are a few test cases that have a reference output like this and it's always annoying: When I later add a new subtest, I add the new test code, review the ./check output and if it looks good, I do something like 'cp 237.out.bad 237.out'. At that point, I'll have to manually revert completely unrelated whitespace changes again.
Is it worth teaching
iotests.img_info_log()to strip trailing whitespace? Or even to teach qemu-img itself to quit generating trailing whitespace?
Not sure if it's worth it, but if someone proposed such a change, I wouldn't object anyway.
Quoted 6 lines
Quoted 1 line
Some 'git am' warnings feel like the lesser evil to me.
True, and a comment in the commit message about intentionally triggering a known checkpatch flag goes a long ways to document why you want the trailing whitespace (assuming we don't instead decide to tackle a root cause of having the whitespace in the first place).
Fair enough. Once it's merged, it doesn't make a difference any more, but it could have made review a bit easier.
Kevin
PATCH v4 5/5 vmdk: Reject excess extents in blockdev-create
In reply to Kevin WolfClarify that the number of extents provided in BlockdevCreateOptionsVmdk must match the number of extents that will actually be used. Providing more extents will result in an error now.
This requires adapting the test case to provide the right number of extents.
--- qapi/block-core.json | 3 ++- block/vmdk.c | 29 ++++++++++++++++++++++++----- tests/qemu-iotests/237 | 6 +++++- tests/qemu-iotests/237.out | 13 +++++++------ 4 files changed, 38 insertions(+), 13 deletions(-)
qapi/block-core.json +2 -1
@@ -4068,7 +4068,8 @@ # twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For # monolithicFlat, only one entry is required; for # twoGbMaxExtent* formats, the number of entries required is -# calculated as extent_number = virtual_size / 2GB. +# calculated as extent_number = virtual_size / 2GB. Providing +# more extents than will be used is an error. # @subformat The subformat of the VMDK image. Default: "monolithicSparse". # @backing-file The path of backing file. Default: no backing file is used. # @adapter-type The adapter type used to fill in the descriptor. Default: ide.
block/vmdk.c +24 -5
@@ -1970,6 +1970,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, {int extent_idx;BlockBackend *blk =NULL ; +BlockBackend *extent_blk;Error *local_err =NULL ;char *desc =NULL ;int ret =0 ;
@@ -2107,7 +2108,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, } extent_idx =1 ;while (created_size < size) { -BlockBackend *extent_blk;int64_t cur_size =MIN (size - created_size, extent_size); extent_blk =extent_fn (cur_size, extent_idx, flat, split, compress, zeroed_grain, opaque, errp);
@@ -2121,6 +2121,17 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, extent_idx++;blk_unref (extent_blk); } + +/* Check whether we got excess extents */ + extent_blk =extent_fn (-1 , extent_idx, flat, split, compress, zeroed_grain, + opaque,NULL ); +if (extent_blk) { +blk_unref (extent_blk); +error_setg (errp,"List of extents contains unused extents" ); + ret = -EINVAL ; + goto exit; + } +/* generate descriptor file */ desc = g_strdup_printf(desc_template, g_random_int(),
@@ -2181,6 +2192,12 @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,char *ext_filename =NULL ;char *rel_filename =NULL ; +/* We're done, don't create excess extents. */ +if (size ==-1 ) { +assert (errp ==NULL ); +return NULL ; + } +if (idx ==0 ) { rel_filename =g_strdup_printf ("%s%s" , data->prefix, data->postfix); }else if (split) {
@@ -2342,10 +2359,12 @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,blk_set_allow_write_beyond_eof (blk, true);bdrv_unref (bs); - ret =vmdk_init_extent (blk, size, flat, compress, zeroed_grain, errp); -if (ret) { -blk_unref (blk); - blk =NULL ; +if (size !=-1 ) { + ret =vmdk_init_extent (blk, size, flat, compress, zeroed_grain, errp); +if (ret) { +blk_unref (blk); + blk =NULL ; + } }return blk; }
tests/qemu-iotests/237 +5 -1
@@ -20,6 +20,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +import math import iotests from iotests import imgfmt
@@ -222,12 +223,15 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("= %s %d =" % (subfmt, size)) iotests.log("") + num_extents = math.ceil(size / 2.0**31) + extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ] + vm.launch() blockdev_create(vm, { 'driver': imgfmt, 'file': 'node0', 'size': size, 'subformat': subfmt, - 'extents': ['ext1', 'ext2', 'ext3'] }) + 'extents': extents }) vm.shutdown() iotests.img_info_log(disk_path)
tests/qemu-iotests/237.out +7 -6
@@ -154,6 +154,7 @@ Job failed: Extent [0] not specified {"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}} {"return": {}} +Job failed: List of extents contains unused extents {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -161,7 +162,7 @@ Job failed: Extent [0] not specified = twoGbMaxExtentFlat 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -181,7 +182,7 @@ Format specific information: = twoGbMaxExtentSparse 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -203,7 +204,7 @@ Format specific information: = twoGbMaxExtentFlat 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -223,7 +224,7 @@ Format specific information: = twoGbMaxExtentSparse 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -245,7 +246,7 @@ Format specific information: = twoGbMaxExtentFlat 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
@@ -265,7 +266,7 @@ Format specific information: = twoGbMaxExtentSparse 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
Signature · 1 line
2.19.2
Re: [Qemu-devel] [PATCH v4 5/5] vmdk: Reject excess extents in blockdev-create
Quoted 68 lines · Kevin Wolf
Clarify that the number of extents provided in BlockdevCreateOptionsVmdk must match the number of extents that will actually be used. Providing more extents will result in an error now.
This requires adapting the test case to provide the right number of extents.
Signed-off-by Kevin Wolf <[email protected]>--- qapi/block-core.json | 3 ++- block/vmdk.c | 29 ++++++++++++++++++++++++----- tests/qemu-iotests/237 | 6 +++++- tests/qemu-iotests/237.out | 13 +++++++------ 4 files changed, 38 insertions(+), 13 deletions(-)qapi/block-core.json +2
-1@@ -4068,7 +4068,8 @@ # twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For # monolithicFlat, only one entry is required; for # twoGbMaxExtent* formats, the number of entries required is -# calculated as extent_number = virtual_size / 2GB. +# calculated as extent_number = virtual_size / 2GB. Providing +# more extents than will be used is an error. # @subformat The subformat of the VMDK image. Default: "monolithicSparse". # @backing-file The path of backing file. Default: no backing file is used. # @adapter-type The adapter type used to fill in the descriptor. Default: ide.block/vmdk.c +12
-1@@ -1970,6 +1970,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, {int extent_idx;BlockBackend *blk =NULL ; +BlockBackend *extent_blk;Error *local_err =NULL ;char *desc =NULL ;int ret =0 ;@@ -2107,7 +2108,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, } extent_idx =1 ;while (created_size < size) { -BlockBackend *extent_blk;int64_t cur_size =MIN (size - created_size, extent_size); extent_blk =extent_fn (cur_size, extent_idx, flat, split, compress, zeroed_grain, opaque, errp);@@ -2121,6 +2121,17 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, extent_idx++;blk_unref (extent_blk); } + +/* Check whether we got excess extents */ + extent_blk =extent_fn (-1 , extent_idx, flat, split, compress, zeroed_grain, + opaque,NULL ); +if (extent_blk) { +blk_unref (extent_blk); +error_setg (errp,"List of extents contains unused extents" ); + ret = -EINVAL ; + goto exit; + } +/* generate descriptor file */ desc = g_strdup_printf(desc_template, g_random_int(),
block/vmdk.c static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx, · line 2200
Quoted 9 lines
block/vmdk.c +6
-0@@ -2181,6 +2192,12 @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,char *ext_filename =NULL ;char *rel_filename =NULL ; +/* We're done, don't create excess extents. */ +if (size ==-1 ) { +assert (errp ==NULL ); +return NULL ; + } +
I'm afraid I don't get this hunk.
Quoted 107 lines
block/vmdk.c +6
-4if (idx ==0 ) { rel_filename =g_strdup_printf ("%s%s" , data->prefix, data->postfix); }else if (split) {@@ -2342,10 +2359,12 @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,blk_set_allow_write_beyond_eof (blk, true);bdrv_unref (bs); - ret =vmdk_init_extent (blk, size, flat, compress, zeroed_grain, errp); -if (ret) { -blk_unref (blk); - blk =NULL ; +if (size !=-1 ) { + ret =vmdk_init_extent (blk, size, flat, compress, zeroed_grain, errp); +if (ret) { +blk_unref (blk); + blk =NULL ; + } }return blk; }tests/qemu-iotests/237 +5
-1@@ -20,6 +20,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +import math import iotests from iotests import imgfmt@@ -222,12 +223,15 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("= %s %d =" % (subfmt, size)) iotests.log("") + num_extents = math.ceil(size / 2.0**31) + extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ] + vm.launch() blockdev_create(vm, { 'driver': imgfmt, 'file': 'node0', 'size': size, 'subformat': subfmt, - 'extents': ['ext1', 'ext2', 'ext3'] }) + 'extents': extents }) vm.shutdown() iotests.img_info_log(disk_path)tests/qemu-iotests/237.out +6
-5@@ -154,6 +154,7 @@ Job failed: Extent [0] not specified {"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}} {"return": {}} +Job failed: List of extents contains unused extents {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}@@ -161,7 +162,7 @@ Job failed: Extent [0] not specified = twoGbMaxExtentFlat 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}@@ -181,7 +182,7 @@ Format specific information: = twoGbMaxExtentSparse 512 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}@@ -203,7 +204,7 @@ Format specific information: = twoGbMaxExtentFlat 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}@@ -223,7 +224,7 @@ Format specific information: = twoGbMaxExtentSparse 1073741824 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}@@ -245,7 +246,7 @@ Format specific information: = twoGbMaxExtentFlat 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
tests/qemu-iotests/237.out Format specific information: · line 272
Quoted 8 lines
tests/qemu-iotests/237.out +1
-1@@ -265,7 +266,7 @@ Format specific information: = twoGbMaxExtentSparse 2147483648 = -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}}
Apart from the hunk that stumps me, the patch looks good to me.
Re: [Qemu-devel] [PATCH v4 5/5] vmdk: Reject excess extents in blockdev-create
Am 07.12.2018 um 14:11 hat Markus Armbruster geschrieben:
Quoted 73 lines
Quoted 71 lines · Kevin Wolf
Clarify that the number of extents provided in BlockdevCreateOptionsVmdk must match the number of extents that will actually be used. Providing more extents will result in an error now.
This requires adapting the test case to provide the right number of extents.
Signed-off-by Kevin Wolf <[email protected]>--- qapi/block-core.json | 3 ++- block/vmdk.c | 29 ++++++++++++++++++++++++----- tests/qemu-iotests/237 | 6 +++++- tests/qemu-iotests/237.out | 13 +++++++------ 4 files changed, 38 insertions(+), 13 deletions(-)qapi/block-core.json +2
-1@@ -4068,7 +4068,8 @@ # twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For # monolithicFlat, only one entry is required; for # twoGbMaxExtent* formats, the number of entries required is -# calculated as extent_number = virtual_size / 2GB. +# calculated as extent_number = virtual_size / 2GB. Providing +# more extents than will be used is an error. # @subformat The subformat of the VMDK image. Default: "monolithicSparse". # @backing-file The path of backing file. Default: no backing file is used. # @adapter-type The adapter type used to fill in the descriptor. Default: ide.block/vmdk.c +12
-1@@ -1970,6 +1970,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, {int extent_idx;BlockBackend *blk =NULL ; +BlockBackend *extent_blk;Error *local_err =NULL ;char *desc =NULL ;int ret =0 ;@@ -2107,7 +2108,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, } extent_idx =1 ;while (created_size < size) { -BlockBackend *extent_blk;int64_t cur_size =MIN (size - created_size, extent_size); extent_blk =extent_fn (cur_size, extent_idx, flat, split, compress, zeroed_grain, opaque, errp);@@ -2121,6 +2121,17 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, extent_idx++;blk_unref (extent_blk); } + +/* Check whether we got excess extents */ + extent_blk =extent_fn (-1 , extent_idx, flat, split, compress, zeroed_grain, + opaque,NULL ); +if (extent_blk) { +blk_unref (extent_blk); +error_setg (errp,"List of extents contains unused extents" ); + ret = -EINVAL ; + goto exit; + } +/* generate descriptor file */ desc = g_strdup_printf(desc_template, g_random_int(),@@ -2181,6 +2192,12 @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,char *ext_filename =NULL ;char *rel_filename =NULL ;
Quoted 8 lines
block/vmdk.c static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx, · line 2200
Quoted 6 lines
block/vmdk.c +6
-0+/* We're done, don't create excess extents. */ +if (size ==-1 ) { +assert (errp ==NULL ); +return NULL ; + } +I'm afraid I don't get this hunk.
vmdk_co_create_opts_cb() is for the legacy code path, where 'qemu-img create' passes us a QemuOpts. This doesn't contain extents, so rather than returning ther next extent from the input, this function simply creates a new extent file each time it is called.
When checking whether we have too many extents, we don't know from which code path we came, so we have to call the callback uncondtionally and see whether it still returns an extra extent. In this case, creating a new one would obviously be counterproductive and trigger an error, so I just return NULL immediately.
If you have a suggestion for a comment to put somewhere, I'll gladly add it.
Kevin
Markus Armbruster
Reviewed-byRe: [Qemu-devel] [PATCH v4 5/5] vmdk: Reject excess extents in blockdev-create
Quoted 88 lines · Kevin Wolf
Am 07.12.2018 um 14:11 hat Markus Armbruster geschrieben:
Quoted 73 lines
Quoted 71 lines · Kevin Wolf
Clarify that the number of extents provided in BlockdevCreateOptionsVmdk must match the number of extents that will actually be used. Providing more extents will result in an error now.
This requires adapting the test case to provide the right number of extents.
Signed-off-by Kevin Wolf <[email protected]>--- qapi/block-core.json | 3 ++- block/vmdk.c | 29 ++++++++++++++++++++++++----- tests/qemu-iotests/237 | 6 +++++- tests/qemu-iotests/237.out | 13 +++++++------ 4 files changed, 38 insertions(+), 13 deletions(-)qapi/block-core.json +2
-1@@ -4068,7 +4068,8 @@ # twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For # monolithicFlat, only one entry is required; for # twoGbMaxExtent* formats, the number of entries required is -# calculated as extent_number = virtual_size / 2GB. +# calculated as extent_number = virtual_size / 2GB. Providing +# more extents than will be used is an error. # @subformat The subformat of the VMDK image. Default: "monolithicSparse". # @backing-file The path of backing file. Default: no backing file is used. # @adapter-type The adapter type used to fill in the descriptor. Default: ide.block/vmdk.c +12
-1@@ -1970,6 +1970,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, {int extent_idx;BlockBackend *blk =NULL ; +BlockBackend *extent_blk;Error *local_err =NULL ;char *desc =NULL ;int ret =0 ;@@ -2107,7 +2108,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, } extent_idx =1 ;while (created_size < size) { -BlockBackend *extent_blk;int64_t cur_size =MIN (size - created_size, extent_size); extent_blk =extent_fn (cur_size, extent_idx, flat, split, compress, zeroed_grain, opaque, errp);@@ -2121,6 +2121,17 @@ static int coroutine_fn vmdk_co_do_create(int64_t size, extent_idx++;blk_unref (extent_blk); } + +/* Check whether we got excess extents */ + extent_blk =extent_fn (-1 , extent_idx, flat, split, compress, zeroed_grain, + opaque,NULL ); +if (extent_blk) { +blk_unref (extent_blk); +error_setg (errp,"List of extents contains unused extents" ); + ret = -EINVAL ; + goto exit; + } +/* generate descriptor file */ desc = g_strdup_printf(desc_template, g_random_int(),@@ -2181,6 +2192,12 @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx,char *ext_filename =NULL ;char *rel_filename =NULL ;Quoted 8 lines
block/vmdk.c static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx, · line 2200
Quoted 6 lines
block/vmdk.c +6
-0+/* We're done, don't create excess extents. */ +if (size ==-1 ) { +assert (errp ==NULL ); +return NULL ; + } +I'm afraid I don't get this hunk.
vmdk_co_create_opts_cb()is for the legacy code path, where 'qemu-img create' passes us a QemuOpts. This doesn't contain extents, so rather than returning ther next extent from the input, this function simply creates a new extent file each time it is called.
Quoted 8 lines
When checking whether we have too many extents, we don't know from which code path we came, so we have to call the callback uncondtionally and see whether it still returns an extra extent. In this case, creating a new one would obviously be counterproductive and trigger an error, so I just return NULL immediately.
If you have a suggestion for a comment to put somewhere, I'll gladly add it.
Coming up with intelligble comments exceed my mental capabilities right now, I'm afraid. But I can still give my
Patchew URL: https://patchew.org/QEMU/[email protected]/
Patchew URL: https://patchew.org/QEMU/[email protected]/
Hi,
This series seems to have some coding style problems. See output below for more information:
Message-id: [email protected]
Subject: [Qemu-devel] [PATCH v4 0/5] vmdk: Implement blockdev-create
Type: series
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
commits="$(git log --format=%H --reverse $BASE..)" for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test'
914b679 vmdk: Reject excess extents in blockdev-create 2721cff iotests: Add VMDK tests for blockdev-create c098e37 iotests: Filter cid numbers in VMDK extent info 3e8f068 vmdk: Implement .bdrv_co_create callback 54b29ff vmdk: Refactor vmdk_create_extent
=== OUTPUT BEGIN ===
Checking PATCH 1/5: vmdk: Refactor vmdk_create_extent...
WARNING: line over 80 characters
#125: FILE: block/vmdk.c:2114:
+ flat, compress, zeroed_grain, NULL, opts, errp)) {
total: 0 errors, 1 warnings, 104 lines checked
Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS.
Checking PATCH 2/5: vmdk: Implement .bdrv_co_create callback...
WARNING: line over 80 characters
#216: FILE: block/vmdk.c:2075:
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
WARNING: line over 80 characters
#371: FILE: block/vmdk.c:2174:
+ bool flat, bool split, bool compress,
WARNING: line over 80 characters
#389: FILE: block/vmdk.c:2192:
+ rel_filename = g_strdup_printf("%s-flat%s", data->prefix, data->postfix);
WARNING: line over 80 characters
#406: FILE: block/vmdk.c:2209:
+static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts,
total: 0 errors, 4 warnings, 658 lines checked
Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS.
Checking PATCH 3/5: iotests: Filter cid numbers in VMDK extent info... Checking PATCH 4/5: iotests: Add VMDK tests for blockdev-create...
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #11:
new file mode 100755
ERROR: trailing whitespace
#282: FILE: tests/qemu-iotests/237.out:28:
+ format: $
ERROR: trailing whitespace
#309: FILE: tests/qemu-iotests/237.out:55:
+ format: $
ERROR: trailing whitespace
#336: FILE: tests/qemu-iotests/237.out:82:
+ format: $
total: 3 errors, 1 warnings, 584 lines checked
Your patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS.
Checking PATCH 5/5: vmdk: Reject excess extents in blockdev-create... === OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/[email protected]/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to [email protected]