Loading blockdev.c +57 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/qmp/types.h" #include "qapi-visit.h" #include "qapi/qmp-output-visitor.h" #include "sysemu/sysemu.h" #include "block/block_int.h" #include "qmp-commands.h" Loading Loading @@ -2066,6 +2068,61 @@ void qmp_block_job_complete(const char *device, Error **errp) block_job_complete(job, errp); } void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; QDict *qdict; DriveInfo *dinfo; Error *local_err = NULL; /* Require an ID in the top level */ if (!options->has_id) { error_setg(errp, "Block device needs an ID"); goto fail; } /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with * cache.direct=false instead of silently switching to aio=threads, except * if called from drive_init. * * For now, simply forbidding the combination for all drivers will do. */ if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) { bool direct = options->cache->has_direct && options->cache->direct; if (!options->has_cache && !direct) { error_setg(errp, "aio=native requires cache.direct=true"); goto fail; } } visit_type_BlockdevOptions(qmp_output_get_visitor(ov), &options, NULL, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); goto fail; } obj = qmp_output_get_qobject(ov); qdict = qobject_to_qdict(obj); qdict_flatten(qdict); QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); goto fail; } dinfo = blockdev_init(opts, IF_NONE); if (!dinfo) { error_setg(errp, "Could not open image"); goto fail; } fail: qmp_output_visitor_cleanup(ov); } static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) { BlockJobInfoList **prev = opaque; Loading qapi-schema.json +236 −0 Original line number Diff line number Diff line Loading @@ -3952,3 +3952,239 @@ ## { 'command': 'query-rx-filter', 'data': { '*name': 'str' }, 'returns': ['RxFilterInfo'] } ## # @BlockdevDiscardOptions # # Determines how to handle discard requests. # # @ignore: Ignore the request # @unmap: Forward as an unmap request # # Since: 1.7 ## { 'enum': 'BlockdevDiscardOptions', 'data': [ 'ignore', 'unmap' ] } ## # @BlockdevAioOptions # # Selects the AIO backend to handle I/O requests # # @threads: Use qemu's thread pool # @native: Use native AIO backend (only Linux and Windows) # # Since: 1.7 ## { 'enum': 'BlockdevAioOptions', 'data': [ 'threads', 'native' ] } ## # @BlockdevCacheOptions # # Includes cache-related options for block devices # # @writeback: #optional enables writeback mode for any caches (default: true) # @direct: #optional enables use of O_DIRECT (bypass the host page cache; # default: false) # @no-flush: #optional ignore any flush requests for the device (default: # false) # # Since: 1.7 ## { 'type': 'BlockdevCacheOptions', 'data': { '*writeback': 'bool', '*direct': 'bool', '*no-flush': 'bool' } } ## # @BlockdevOptionsBase # # Options that are available for all block devices, independent of the block # driver. # # @driver: block driver name # @id: #optional id by which the new block device can be referred to. # This is a required option on the top level of blockdev-add, and # currently not allowed on any other level. # @discard: #optional discard-related options (default: ignore) # @cache: #optional cache-related options # @aio: #optional AIO backend (default: threads) # @rerror: #optional how to handle read errors on the device # (default: report) # @werror: #optional how to handle write errors on the device # (default: enospc) # @read-only: #optional whether the block device should be read-only # (default: false) # # Since: 1.7 ## { 'type': 'BlockdevOptionsBase', 'data': { 'driver': 'str', '*id': 'str', '*discard': 'BlockdevDiscardOptions', '*cache': 'BlockdevCacheOptions', '*aio': 'BlockdevAioOptions', '*rerror': 'BlockdevOnError', '*werror': 'BlockdevOnError', '*read-only': 'bool' } } ## # @BlockdevOptionsFile # # Driver specific block device options for the file backend and similar # protocols. # # @filename: path to the image file # # Since: 1.7 ## { 'type': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } } ## # @BlockdevOptionsVVFAT # # Driver specific block device options for the vvfat protocol. # # @dir: directory to be exported as FAT image # @fat-type: #optional FAT type: 12, 16 or 32 # @floppy: #optional whether to export a floppy image (true) or # partitioned hard disk (false; default) # @rw: #optional whether to allow write operations (default: false) # # Since: 1.7 ## { 'type': 'BlockdevOptionsVVFAT', 'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool', '*rw': 'bool' } } ## # @BlockdevOptionsGenericFormat # # Driver specific block device options for image format that have no option # besides their data source. # # @file: reference to or definition of the data source block device # # Since: 1.7 ## { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'BlockdevRef' } } ## # @BlockdevOptionsGenericCOWFormat # # Driver specific block device options for image format that have no option # besides their data source and an optional backing file. # # @backing: #optional reference to or definition of the backing file block # device (if missing, taken from the image file content). It is # allowed to pass an empty string here in order to disable the # default backing file. # # Since: 1.7 ## { 'type': 'BlockdevOptionsGenericCOWFormat', 'base': 'BlockdevOptionsGenericFormat', 'data': { '*backing': 'BlockdevRef' } } ## # @BlockdevOptionsQcow2 # # Driver specific block device options for qcow2. # # @lazy-refcounts: #optional whether to enable the lazy refcounts # feature (default is taken from the image file) # # @pass-discard-request: #optional whether discard requests to the qcow2 # device should be forwarded to the data source # # @pass-discard-snapshot: #optional whether discard requests for the data source # should be issued when a snapshot operation (e.g. # deleting a snapshot) frees clusters in the qcow2 file # # @pass-discard-other: #optional whether discard requests for the data source # should be issued on other occasions where a cluster # gets freed # # Since: 1.7 ## { 'type': 'BlockdevOptionsQcow2', 'base': 'BlockdevOptionsGenericCOWFormat', 'data': { '*lazy-refcounts': 'bool', '*pass-discard-request': 'bool', '*pass-discard-snapshot': 'bool', '*pass-discard-other': 'bool' } } ## # @BlockdevOptions # # Options for creating a block device. # # Since: 1.7 ## { 'union': 'BlockdevOptions', 'base': 'BlockdevOptionsBase', 'discriminator': 'driver', 'data': { 'file': 'BlockdevOptionsFile', 'http': 'BlockdevOptionsFile', 'https': 'BlockdevOptionsFile', 'ftp': 'BlockdevOptionsFile', 'ftps': 'BlockdevOptionsFile', 'tftp': 'BlockdevOptionsFile', # TODO gluster: Wait for structured options # TODO iscsi: Wait for structured options # TODO nbd: Should take InetSocketAddress for 'host'? # TODO rbd: Wait for structured options # TODO sheepdog: Wait for structured options # TODO ssh: Should take InetSocketAddress for 'host'? 'vvfat': 'BlockdevOptionsVVFAT', # TODO blkdebug: Wait for structured options # TODO blkverify: Wait for structured options 'bochs': 'BlockdevOptionsGenericFormat', 'cloop': 'BlockdevOptionsGenericFormat', 'cow': 'BlockdevOptionsGenericCOWFormat', 'dmg': 'BlockdevOptionsGenericFormat', 'parallels': 'BlockdevOptionsGenericFormat', 'qcow': 'BlockdevOptionsGenericCOWFormat', 'qcow2': 'BlockdevOptionsQcow2', 'qed': 'BlockdevOptionsGenericCOWFormat', 'raw': 'BlockdevOptionsGenericFormat', 'vdi': 'BlockdevOptionsGenericFormat', 'vhdx': 'BlockdevOptionsGenericFormat', 'vmdk': 'BlockdevOptionsGenericCOWFormat', 'vpc': 'BlockdevOptionsGenericFormat' } } ## # @BlockdevRef # # Reference to a block device. # # @definition: defines a new block device inline # @reference: references the ID of an existing block device. An # empty string means that no block device should be # referenced. # # Since: 1.7 ## { 'union': 'BlockdevRef', 'discriminator': {}, 'data': { 'definition': 'BlockdevOptions', 'reference': 'str' } } ## # @blockdev-add: # # Creates a new block device. # # @options: block device options for the new device # # Since: 1.7 ## { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } } qmp-commands.hx +55 −0 Original line number Diff line number Diff line Loading @@ -3239,4 +3239,59 @@ Example: ] } EQMP { .name = "blockdev-add", .args_type = "options:q", .mhandler.cmd_new = qmp_marshal_input_blockdev_add, }, SQMP blockdev-add ------------ Add a block device. Arguments: - "options": block driver options Example (1): -> { "execute": "blockdev-add", "arguments": { "options" : { "driver": "qcow2", "file": { "driver": "file", "filename": "test.qcow2" } } } } <- { "return": {} } Example (2): -> { "execute": "blockdev-add", "arguments": { "options": { "driver": "qcow2", "id": "my_disk", "discard": "unmap", "cache": { "direct": true, "writeback": true }, "file": { "driver": "file", "filename": "/tmp/test.qcow2" }, "backing": { "driver": "raw", "file": { "driver": "file", "filename": "/dev/fdset/4" } } } } } <- { "return": {} } EQMP Loading
blockdev.c +57 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qapi/qmp/types.h" #include "qapi-visit.h" #include "qapi/qmp-output-visitor.h" #include "sysemu/sysemu.h" #include "block/block_int.h" #include "qmp-commands.h" Loading Loading @@ -2066,6 +2068,61 @@ void qmp_block_job_complete(const char *device, Error **errp) block_job_complete(job, errp); } void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; QDict *qdict; DriveInfo *dinfo; Error *local_err = NULL; /* Require an ID in the top level */ if (!options->has_id) { error_setg(errp, "Block device needs an ID"); goto fail; } /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with * cache.direct=false instead of silently switching to aio=threads, except * if called from drive_init. * * For now, simply forbidding the combination for all drivers will do. */ if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) { bool direct = options->cache->has_direct && options->cache->direct; if (!options->has_cache && !direct) { error_setg(errp, "aio=native requires cache.direct=true"); goto fail; } } visit_type_BlockdevOptions(qmp_output_get_visitor(ov), &options, NULL, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); goto fail; } obj = qmp_output_get_qobject(ov); qdict = qobject_to_qdict(obj); qdict_flatten(qdict); QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); goto fail; } dinfo = blockdev_init(opts, IF_NONE); if (!dinfo) { error_setg(errp, "Could not open image"); goto fail; } fail: qmp_output_visitor_cleanup(ov); } static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) { BlockJobInfoList **prev = opaque; Loading
qapi-schema.json +236 −0 Original line number Diff line number Diff line Loading @@ -3952,3 +3952,239 @@ ## { 'command': 'query-rx-filter', 'data': { '*name': 'str' }, 'returns': ['RxFilterInfo'] } ## # @BlockdevDiscardOptions # # Determines how to handle discard requests. # # @ignore: Ignore the request # @unmap: Forward as an unmap request # # Since: 1.7 ## { 'enum': 'BlockdevDiscardOptions', 'data': [ 'ignore', 'unmap' ] } ## # @BlockdevAioOptions # # Selects the AIO backend to handle I/O requests # # @threads: Use qemu's thread pool # @native: Use native AIO backend (only Linux and Windows) # # Since: 1.7 ## { 'enum': 'BlockdevAioOptions', 'data': [ 'threads', 'native' ] } ## # @BlockdevCacheOptions # # Includes cache-related options for block devices # # @writeback: #optional enables writeback mode for any caches (default: true) # @direct: #optional enables use of O_DIRECT (bypass the host page cache; # default: false) # @no-flush: #optional ignore any flush requests for the device (default: # false) # # Since: 1.7 ## { 'type': 'BlockdevCacheOptions', 'data': { '*writeback': 'bool', '*direct': 'bool', '*no-flush': 'bool' } } ## # @BlockdevOptionsBase # # Options that are available for all block devices, independent of the block # driver. # # @driver: block driver name # @id: #optional id by which the new block device can be referred to. # This is a required option on the top level of blockdev-add, and # currently not allowed on any other level. # @discard: #optional discard-related options (default: ignore) # @cache: #optional cache-related options # @aio: #optional AIO backend (default: threads) # @rerror: #optional how to handle read errors on the device # (default: report) # @werror: #optional how to handle write errors on the device # (default: enospc) # @read-only: #optional whether the block device should be read-only # (default: false) # # Since: 1.7 ## { 'type': 'BlockdevOptionsBase', 'data': { 'driver': 'str', '*id': 'str', '*discard': 'BlockdevDiscardOptions', '*cache': 'BlockdevCacheOptions', '*aio': 'BlockdevAioOptions', '*rerror': 'BlockdevOnError', '*werror': 'BlockdevOnError', '*read-only': 'bool' } } ## # @BlockdevOptionsFile # # Driver specific block device options for the file backend and similar # protocols. # # @filename: path to the image file # # Since: 1.7 ## { 'type': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } } ## # @BlockdevOptionsVVFAT # # Driver specific block device options for the vvfat protocol. # # @dir: directory to be exported as FAT image # @fat-type: #optional FAT type: 12, 16 or 32 # @floppy: #optional whether to export a floppy image (true) or # partitioned hard disk (false; default) # @rw: #optional whether to allow write operations (default: false) # # Since: 1.7 ## { 'type': 'BlockdevOptionsVVFAT', 'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool', '*rw': 'bool' } } ## # @BlockdevOptionsGenericFormat # # Driver specific block device options for image format that have no option # besides their data source. # # @file: reference to or definition of the data source block device # # Since: 1.7 ## { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'BlockdevRef' } } ## # @BlockdevOptionsGenericCOWFormat # # Driver specific block device options for image format that have no option # besides their data source and an optional backing file. # # @backing: #optional reference to or definition of the backing file block # device (if missing, taken from the image file content). It is # allowed to pass an empty string here in order to disable the # default backing file. # # Since: 1.7 ## { 'type': 'BlockdevOptionsGenericCOWFormat', 'base': 'BlockdevOptionsGenericFormat', 'data': { '*backing': 'BlockdevRef' } } ## # @BlockdevOptionsQcow2 # # Driver specific block device options for qcow2. # # @lazy-refcounts: #optional whether to enable the lazy refcounts # feature (default is taken from the image file) # # @pass-discard-request: #optional whether discard requests to the qcow2 # device should be forwarded to the data source # # @pass-discard-snapshot: #optional whether discard requests for the data source # should be issued when a snapshot operation (e.g. # deleting a snapshot) frees clusters in the qcow2 file # # @pass-discard-other: #optional whether discard requests for the data source # should be issued on other occasions where a cluster # gets freed # # Since: 1.7 ## { 'type': 'BlockdevOptionsQcow2', 'base': 'BlockdevOptionsGenericCOWFormat', 'data': { '*lazy-refcounts': 'bool', '*pass-discard-request': 'bool', '*pass-discard-snapshot': 'bool', '*pass-discard-other': 'bool' } } ## # @BlockdevOptions # # Options for creating a block device. # # Since: 1.7 ## { 'union': 'BlockdevOptions', 'base': 'BlockdevOptionsBase', 'discriminator': 'driver', 'data': { 'file': 'BlockdevOptionsFile', 'http': 'BlockdevOptionsFile', 'https': 'BlockdevOptionsFile', 'ftp': 'BlockdevOptionsFile', 'ftps': 'BlockdevOptionsFile', 'tftp': 'BlockdevOptionsFile', # TODO gluster: Wait for structured options # TODO iscsi: Wait for structured options # TODO nbd: Should take InetSocketAddress for 'host'? # TODO rbd: Wait for structured options # TODO sheepdog: Wait for structured options # TODO ssh: Should take InetSocketAddress for 'host'? 'vvfat': 'BlockdevOptionsVVFAT', # TODO blkdebug: Wait for structured options # TODO blkverify: Wait for structured options 'bochs': 'BlockdevOptionsGenericFormat', 'cloop': 'BlockdevOptionsGenericFormat', 'cow': 'BlockdevOptionsGenericCOWFormat', 'dmg': 'BlockdevOptionsGenericFormat', 'parallels': 'BlockdevOptionsGenericFormat', 'qcow': 'BlockdevOptionsGenericCOWFormat', 'qcow2': 'BlockdevOptionsQcow2', 'qed': 'BlockdevOptionsGenericCOWFormat', 'raw': 'BlockdevOptionsGenericFormat', 'vdi': 'BlockdevOptionsGenericFormat', 'vhdx': 'BlockdevOptionsGenericFormat', 'vmdk': 'BlockdevOptionsGenericCOWFormat', 'vpc': 'BlockdevOptionsGenericFormat' } } ## # @BlockdevRef # # Reference to a block device. # # @definition: defines a new block device inline # @reference: references the ID of an existing block device. An # empty string means that no block device should be # referenced. # # Since: 1.7 ## { 'union': 'BlockdevRef', 'discriminator': {}, 'data': { 'definition': 'BlockdevOptions', 'reference': 'str' } } ## # @blockdev-add: # # Creates a new block device. # # @options: block device options for the new device # # Since: 1.7 ## { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
qmp-commands.hx +55 −0 Original line number Diff line number Diff line Loading @@ -3239,4 +3239,59 @@ Example: ] } EQMP { .name = "blockdev-add", .args_type = "options:q", .mhandler.cmd_new = qmp_marshal_input_blockdev_add, }, SQMP blockdev-add ------------ Add a block device. Arguments: - "options": block driver options Example (1): -> { "execute": "blockdev-add", "arguments": { "options" : { "driver": "qcow2", "file": { "driver": "file", "filename": "test.qcow2" } } } } <- { "return": {} } Example (2): -> { "execute": "blockdev-add", "arguments": { "options": { "driver": "qcow2", "id": "my_disk", "discard": "unmap", "cache": { "direct": true, "writeback": true }, "file": { "driver": "file", "filename": "/tmp/test.qcow2" }, "backing": { "driver": "raw", "file": { "driver": "file", "filename": "/dev/fdset/4" } } } } } <- { "return": {} } EQMP