Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging

Block layer patches

# gpg: Signature made Fri 23 Sep 2016 12:59:46 BST
# gpg:                using RSA key 0x7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream: (33 commits)
  block: Remove BB interface from blockdev-add/del
  qemu-iotests/141: Avoid blockdev-add with id
  block: Avoid printing NULL string in error messages
  qemu-iotests/139: Avoid blockdev-add with id
  qemu-iotests/124: Avoid blockdev-add with id
  qemu-iotests/118: Avoid blockdev-add with id
  qemu-iotests/117: Avoid blockdev-add with id
  qemu-iotests/087: Avoid blockdev-add with id
  qemu-iotests/081: Avoid blockdev-add with id
  qemu-iotests/071: Avoid blockdev-add with id
  qemu-iotests/067: Avoid blockdev-add with id
  qemu-iotests/041: Avoid blockdev-add with id
  qemu-iotests/118: Test media change with qdev name
  block: Accept device model name for block_set_io_throttle
  block: Accept device model name for blockdev-change-medium
  block: Accept device model name for eject
  block: Accept device model name for x-blockdev-remove-medium
  block: Accept device model name for x-blockdev-insert-medium
  block: Accept device model name for blockdev-open/close-tray
  qdev-monitor: Add blk_by_qdev_id()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2016-09-23 16:15:33 +01:00
35 changed files with 850 additions and 670 deletions
+65 -24
View File
@@ -733,6 +733,9 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
/* Copy the read-only option from the parent */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
/* aio=native doesn't work for cache.direct=off, so disable it for the
* temporary snapshot */
*child_flags &= ~BDRV_O_NATIVE_AIO;
@@ -755,6 +758,9 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
/* Inherit the read-only option from the parent if it's not set */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
/* Our block drivers take care to send flushes and respect unmap policy,
* so we can default to enable both on lower layers regardless of the
* corresponding parent options. */
@@ -808,7 +814,8 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
/* backing files always opened read-only */
flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
flags &= ~BDRV_O_COPY_ON_READ;
/* snapshot=on is handled on the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
@@ -855,6 +862,14 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
*flags |= BDRV_O_NOCACHE;
}
*flags &= ~BDRV_O_RDWR;
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
if (!qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false)) {
*flags |= BDRV_O_RDWR;
}
}
static void update_options_from_flags(QDict *options, int flags)
@@ -867,6 +882,10 @@ static void update_options_from_flags(QDict *options, int flags)
qdict_put(options, BDRV_OPT_CACHE_NO_FLUSH,
qbool_from_bool(flags & BDRV_O_NO_FLUSH));
}
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
qdict_put(options, BDRV_OPT_READ_ONLY,
qbool_from_bool(!(flags & BDRV_O_RDWR)));
}
}
static void bdrv_assign_node_name(BlockDriverState *bs,
@@ -930,6 +949,11 @@ static QemuOptsList bdrv_runtime_opts = {
.type = QEMU_OPT_BOOL,
.help = "Ignore flush requests",
},
{
.name = BDRV_OPT_READ_ONLY,
.type = QEMU_OPT_BOOL,
.help = "Node is opened in read-only mode",
},
{ /* end of list */ }
},
};
@@ -961,6 +985,8 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
goto fail_opts;
}
update_flags_from_options(&bs->open_flags, opts);
driver_name = qemu_opt_get(opts, "driver");
drv = bdrv_find_format(driver_name);
assert(drv != NULL);
@@ -1022,9 +1048,6 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
bs->drv = drv;
bs->opaque = g_malloc0(drv->instance_size);
/* Apply cache mode options */
update_flags_from_options(&bs->open_flags, opts);
/* Open the image, either directly or using a protocol */
open_flags = bdrv_open_flags(bs, bs->open_flags);
if (drv->bdrv_file_open) {
@@ -1675,6 +1698,25 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
goto fail;
}
/* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.
* FIXME: we're parsing the QDict to avoid having to create a
* QemuOpts just for this, but neither option is optimal. */
if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") &&
!qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) {
flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR);
} else {
flags &= ~BDRV_O_RDWR;
}
if (flags & BDRV_O_SNAPSHOT) {
snapshot_options = qdict_new();
bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
flags, options);
/* Let bdrv_backing_options() override "read-only" */
qdict_del(options, BDRV_OPT_READ_ONLY);
bdrv_backing_options(&flags, options, flags, options);
}
bs->open_flags = flags;
bs->options = options;
options = qdict_clone_shallow(options);
@@ -1699,18 +1741,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
/* Open image file without format layer */
if ((flags & BDRV_O_PROTOCOL) == 0) {
if (flags & BDRV_O_RDWR) {
flags |= BDRV_O_ALLOW_RDWR;
}
if (flags & BDRV_O_SNAPSHOT) {
snapshot_options = qdict_new();
bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
flags, options);
bdrv_backing_options(&flags, options, flags, options);
}
bs->open_flags = flags;
file = bdrv_open_child(filename, options, "file", bs,
&child_file, true, &local_err);
if (local_err) {
@@ -1895,6 +1925,13 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
options = qdict_new();
}
/* Check if this BlockDriverState is already in the queue */
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
if (bs == bs_entry->state.bs) {
break;
}
}
/*
* Precedence of options:
* 1. Explicitly passed in options (highest)
@@ -1915,7 +1952,11 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
}
/* Old explicitly set values (don't overwrite by inherited value) */
old_options = qdict_clone_shallow(bs->explicit_options);
if (bs_entry) {
old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
} else {
old_options = qdict_clone_shallow(bs->explicit_options);
}
bdrv_join_options(bs, options, old_options);
QDECREF(old_options);
@@ -1954,8 +1995,13 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
child->role, options, flags);
}
bs_entry = g_new0(BlockReopenQueueEntry, 1);
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
if (!bs_entry) {
bs_entry = g_new0(BlockReopenQueueEntry, 1);
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
} else {
QDECREF(bs_entry->state.options);
QDECREF(bs_entry->state.explicit_options);
}
bs_entry->state.bs = bs;
bs_entry->state.options = options;
@@ -3013,11 +3059,6 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
return false;
}
int bdrv_is_snapshot(BlockDriverState *bs)
{
return !!(bs->open_flags & BDRV_O_SNAPSHOT);
}
/* backing_file can either be relative, or absolute, or a protocol. If it is
* relative, it must be relative to the chain. So, passing in bs->filename
* from a BDS as backing_file should not be done, as that may be relative to
+19
View File
@@ -559,6 +559,25 @@ void *blk_get_attached_dev(BlockBackend *blk)
return blk->dev;
}
/*
* Return the BlockBackend which has the device model @dev attached if it
* exists, else null.
*
* @dev must not be null.
*/
BlockBackend *blk_by_dev(void *dev)
{
BlockBackend *blk = NULL;
assert(dev != NULL);
while ((blk = blk_all_next(blk)) != NULL) {
if (blk->dev == dev) {
return blk;
}
}
return NULL;
}
/*
* Set @blk's device model callbacks to @ops.
* @opaque is the opaque argument to pass to the callbacks.
+4 -4
View File
@@ -242,14 +242,14 @@ void commit_start(const char *job_id, BlockDriverState *bs,
orig_overlay_flags = bdrv_get_flags(overlay_bs);
/* convert base & overlay_bs to r/w, if necessary */
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL,
orig_overlay_flags | BDRV_O_RDWR);
}
if (!(orig_base_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
orig_base_flags | BDRV_O_RDWR);
}
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL,
orig_overlay_flags | BDRV_O_RDWR);
}
if (reopen_queue) {
bdrv_reopen_multiple(reopen_queue, &local_err);
if (local_err != NULL) {
+1 -1
View File
@@ -429,7 +429,7 @@ static int coroutine_fn do_perform_cow(BlockDriverState *bs,
if (bs->encrypted) {
Error *err = NULL;
int64_t sector = (cluster_offset + offset_in_cluster)
int64_t sector = (src_cluster_offset + offset_in_cluster)
>> BDRV_SECTOR_BITS;
assert(s->cipher);
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
+2 -1
View File
@@ -2971,7 +2971,8 @@ static BlockDriver vvfat_write_target = {
static void vvfat_qcow_options(int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
*child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
*child_flags = BDRV_O_NO_FLUSH;
}
static const BdrvChildRole child_vvfat_qcow = {
+149 -164
View File
File diff suppressed because it is too large Load Diff
+41 -37
View File
@@ -72,12 +72,14 @@ Eject a removable medium.
Arguments:
- force: force ejection (json-bool, optional)
- device: device name (json-string)
- "force": force ejection (json-bool, optional)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
Example:
-> { "execute": "eject", "arguments": { "device": "ide1-cd0" } }
-> { "execute": "eject", "arguments": { "id": "ide0-1-0" } }
<- { "return": {} }
Note: The "force" argument defaults to false.
@@ -1457,7 +1459,9 @@ Change I/O throttle limits for a block drive.
Arguments:
- "device": device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
- "bps": total throughput limit in bytes per second (json-int)
- "bps_rd": read throughput limit in bytes per second (json-int)
- "bps_wr": write throughput limit in bytes per second (json-int)
@@ -1481,7 +1485,7 @@ Arguments:
Example:
-> { "execute": "block_set_io_throttle", "arguments": { "device": "virtio0",
-> { "execute": "block_set_io_throttle", "arguments": { "id": "ide0-1-0",
"bps": 1000000,
"bps_rd": 0,
"bps_wr": 0,
@@ -3137,7 +3141,7 @@ Example (2):
"arguments": {
"options": {
"driver": "qcow2",
"id": "my_disk",
"node-name": "my_disk",
"discard": "unmap",
"cache": {
"direct": true,
@@ -3164,18 +3168,9 @@ x-blockdev-del
------------
Since 2.5
Deletes a block device thas has been added using blockdev-add.
The selected device can be either a block backend or a graph node.
In the former case the backend will be destroyed, along with its
inserted medium if there's any. The command will fail if the backend
or its medium are in use.
In the latter case the node will be destroyed. The command will fail
if the node is attached to a block backend or is otherwise being
used.
One of "id" or "node-name" must be specified, but not both.
Deletes a block device that has been added using blockdev-add.
The command will fail if the node is attached to a device or is
otherwise being used.
This command is still a work in progress and is considered
experimental. Stay away from it unless you want to help with its
@@ -3183,8 +3178,7 @@ development.
Arguments:
- "id": Name of the block backend device to delete (json-string, optional)
- "node-name": Name of the graph node to delete (json-string, optional)
- "node-name": Name of the graph node to delete (json-string)
Example:
@@ -3192,7 +3186,7 @@ Example:
"arguments": {
"options": {
"driver": "qcow2",
"id": "drive0",
"node-name": "node0",
"file": {
"driver": "file",
"filename": "test.qcow2"
@@ -3204,7 +3198,7 @@ Example:
<- { "return": {} }
-> { "execute": "x-blockdev-del",
"arguments": { "id": "drive0" }
"arguments": { "node-name": "node0" }
}
<- { "return": {} }
@@ -3228,7 +3222,9 @@ which no such event will be generated, these include:
Arguments:
- "device": block device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
- "force": if false (the default), an eject request will be sent to the guest if
it has locked the tray (and the tray will not be opened immediately);
if true, the tray will be opened regardless of whether it is locked
@@ -3237,7 +3233,7 @@ Arguments:
Example:
-> { "execute": "blockdev-open-tray",
"arguments": { "device": "ide1-cd0" } }
"arguments": { "id": "ide0-1-0" } }
<- { "timestamp": { "seconds": 1418751016,
"microseconds": 716996 },
@@ -3258,12 +3254,14 @@ If the tray was already closed before, this will be a no-op.
Arguments:
- "device": block device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
Example:
-> { "execute": "blockdev-close-tray",
"arguments": { "device": "ide1-cd0" } }
"arguments": { "id": "ide0-1-0" } }
<- { "timestamp": { "seconds": 1418751345,
"microseconds": 272147 },
@@ -3286,18 +3284,20 @@ Stay away from it unless you want to help with its development.
Arguments:
- "device": block device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
Example:
-> { "execute": "x-blockdev-remove-medium",
"arguments": { "device": "ide1-cd0" } }
"arguments": { "id": "ide0-1-0" } }
<- { "error": { "class": "GenericError",
"desc": "Tray of device 'ide1-cd0' is not open" } }
"desc": "Tray of device 'ide0-1-0' is not open" } }
-> { "execute": "blockdev-open-tray",
"arguments": { "device": "ide1-cd0" } }
"arguments": { "id": "ide0-1-0" } }
<- { "timestamp": { "seconds": 1418751627,
"microseconds": 549958 },
@@ -3308,7 +3308,7 @@ Example:
<- { "return": {} }
-> { "execute": "x-blockdev-remove-medium",
"arguments": { "device": "ide1-cd0" } }
"arguments": { "device": "ide0-1-0" } }
<- { "return": {} }
@@ -3324,7 +3324,9 @@ Stay away from it unless you want to help with its development.
Arguments:
- "device": block device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
- "node-name": root node of the BDS tree to insert into the block device
Example:
@@ -3338,7 +3340,7 @@ Example:
<- { "return": {} }
-> { "execute": "x-blockdev-insert-medium",
"arguments": { "device": "ide1-cd0",
"arguments": { "id": "ide0-1-0",
"node-name": "node0" } }
<- { "return": {} }
@@ -3448,7 +3450,9 @@ and loading a new image file which is inserted as the new medium.
Arguments:
- "device": device name (json-string)
- "device": block device name (deprecated, use @id instead)
(json-string, optional)
- "id": the name or QOM path of the guest device (json-string, optional)
- "filename": filename of the new image (json-string)
- "format": format of the new image (json-string, optional)
- "read-only-mode": new read-only mode (json-string, optional)
@@ -3459,7 +3463,7 @@ Examples:
1. Change a removable medium
-> { "execute": "blockdev-change-medium",
"arguments": { "device": "ide1-cd0",
"arguments": { "id": "ide0-1-0",
"filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
"format": "raw" } }
<- { "return": {} }
@@ -3467,7 +3471,7 @@ Examples:
2. Load a read-only medium into a writable drive
-> { "execute": "blockdev-change-medium",
"arguments": { "device": "isa-fd0",
"arguments": { "id": "floppyA",
"filename": "/srv/images/ro.img",
"format": "raw",
"read-only-mode": "retain" } }
@@ -3477,7 +3481,7 @@ Examples:
"desc": "Could not open '/srv/images/ro.img': Permission denied" } }
-> { "execute": "blockdev-change-medium",
"arguments": { "device": "isa-fd0",
"arguments": { "id": "floppyA",
"filename": "/srv/images/ro.img",
"format": "raw",
"read-only-mode": "read-only" } }
+9 -12
View File
@@ -1376,7 +1376,7 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
const char *device = qdict_get_str(qdict, "device");
Error *err = NULL;
qmp_eject(device, true, force, &err);
qmp_eject(true, device, false, NULL, true, force, &err);
hmp_handle_error(mon, &err);
}
@@ -1422,8 +1422,9 @@ void hmp_change(Monitor *mon, const QDict *qdict)
}
}
qmp_blockdev_change_medium(device, target, !!arg, arg,
!!read_only, read_only_mode, &err);
qmp_blockdev_change_medium(true, device, false, NULL, target,
!!arg, arg, !!read_only, read_only_mode,
&err);
if (err &&
error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
error_free(err);
@@ -1924,6 +1925,7 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
BlockBackend *blk;
BlockBackend *local_blk = NULL;
AioContext *aio_context;
const char* device = qdict_get_str(qdict, "device");
const char* command = qdict_get_str(qdict, "command");
Error *err = NULL;
@@ -1939,17 +1941,12 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
}
}
if (blk) {
AioContext *aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
qemuio_command(blk, command);
qemuio_command(blk, command);
aio_context_release(aio_context);
} else {
error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
}
aio_context_release(aio_context);
fail:
blk_unref(local_blk);
+1 -1
View File
@@ -107,6 +107,7 @@ typedef struct HDGeometry {
#define BDRV_OPT_CACHE_WB "cache.writeback"
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
#define BDRV_OPT_READ_ONLY "read-only"
#define BDRV_SECTOR_BITS 9
@@ -414,7 +415,6 @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
const char *backing,
char *dest, size_t sz,
Error **errp);
int bdrv_is_snapshot(BlockDriverState *bs);
int path_has_protocol(const char *path);
int path_is_absolute(const char *path);
+2
View File
@@ -111,6 +111,8 @@ int blk_attach_dev(BlockBackend *blk, void *dev);
void blk_attach_dev_nofail(BlockBackend *blk, void *dev);
void blk_detach_dev(BlockBackend *blk, void *dev);
void *blk_get_attached_dev(BlockBackend *blk);
BlockBackend *blk_by_dev(void *dev);
BlockBackend *blk_by_qdev_id(const char *id, Error **errp);
void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque);
int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
int count);
+39 -39
View File
@@ -900,7 +900,7 @@
# otherwise. (Since 2.4)
#
# @compress: #optional true to compress data, if the target format supports it.
# (default: false) (since 2.7)
# (default: false) (since 2.8)
#
# @on-source-error: #optional the action to take on an error on the source,
# default 'report'. 'stop' and 'enospc' can only be used
@@ -941,7 +941,7 @@
# for unlimited.
#
# @compress: #optional true to compress data, if the target format supports it.
# (default: false) (since 2.7)
# (default: false) (since 2.8)
#
# @on-source-error: #optional the action to take on an error on the source,
# default 'report'. 'stop' and 'enospc' can only be used
@@ -1377,7 +1377,9 @@
#
# A set of parameters describing block throttling.
#
# @device: The name of the device
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @bps: total throughput limit in bytes per second
#
@@ -1446,8 +1448,8 @@
# Since: 1.1
##
{ 'struct': 'BlockIOThrottle',
'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
'data': { '*device': 'str', '*id': 'str', 'bps': 'int', 'bps_rd': 'int',
'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
'*bps_max': 'int', '*bps_rd_max': 'int',
'*bps_wr_max': 'int', '*iops_max': 'int',
'*iops_rd_max': 'int', '*iops_wr_max': 'int',
@@ -2215,13 +2217,8 @@
# 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 option is only allowed on the top level of blockdev-add.
# A BlockBackend will be created by blockdev-add if and only if
# this option is given.
# @node-name: #optional the name of a block driver state node (Since 2.0).
# This option is required on the top level of blockdev-add if
# the @id option is not given there.
# @node-name: #optional the node name of the new node (Since 2.0).
# This option is required on the top level of blockdev-add.
# @discard: #optional discard-related options (default: ignore)
# @cache: #optional cache-related options
# @aio: #optional AIO backend (default: threads)
@@ -2236,8 +2233,6 @@
##
{ 'union': 'BlockdevOptions',
'base': { 'driver': 'BlockdevDriver',
# TODO 'id' is a BB-level option, remove it
'*id': 'str',
'*node-name': 'str',
'*discard': 'BlockdevDiscardOptions',
'*cache': 'BlockdevCacheOptions',
@@ -2321,29 +2316,18 @@
# @x-blockdev-del:
#
# Deletes a block device that has been added using blockdev-add.
# The selected device can be either a block backend or a graph node.
#
# In the former case the backend will be destroyed, along with its
# inserted medium if there's any. The command will fail if the backend
# or its medium are in use.
#
# In the latter case the node will be destroyed. The command will fail
# if the node is attached to a block backend or is otherwise being
# used.
#
# One of @id or @node-name must be specified, but not both.
# The command will fail if the node is attached to a device or is
# otherwise being used.
#
# This command is still a work in progress and is considered
# experimental. Stay away from it unless you want to help with its
# development.
#
# @id: #optional Name of the block backend device to delete.
#
# @node-name: #optional Name of the graph node to delete.
# @node-name: Name of the graph node to delete.
#
# Since: 2.5
##
{ 'command': 'x-blockdev-del', 'data': { '*id': 'str', '*node-name': 'str' } }
{ 'command': 'x-blockdev-del', 'data': { 'node-name': 'str' } }
##
# @blockdev-open-tray:
@@ -2363,7 +2347,9 @@
# to it
# - if the guest device does not have an actual tray
#
# @device: block device name
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @force: #optional if false (the default), an eject request will be sent to
# the guest if it has locked the tray (and the tray will not be opened
@@ -2373,7 +2359,8 @@
# Since: 2.5
##
{ 'command': 'blockdev-open-tray',
'data': { 'device': 'str',
'data': { '*device': 'str',
'*id': 'str',
'*force': 'bool' } }
##
@@ -2385,12 +2372,15 @@
#
# If the tray was already closed before, this will be a no-op.
#
# @device: block device name
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# Since: 2.5
##
{ 'command': 'blockdev-close-tray',
'data': { 'device': 'str' } }
'data': { '*device': 'str',
'*id': 'str' } }
##
# @x-blockdev-remove-medium:
@@ -2404,12 +2394,15 @@
# This command is still a work in progress and is considered experimental.
# Stay away from it unless you want to help with its development.
#
# @device: block device name
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# Since: 2.5
##
{ 'command': 'x-blockdev-remove-medium',
'data': { 'device': 'str' } }
'data': { '*device': 'str',
'*id': 'str' } }
##
# @x-blockdev-insert-medium:
@@ -2421,14 +2414,17 @@
# This command is still a work in progress and is considered experimental.
# Stay away from it unless you want to help with its development.
#
# @device: block device name
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @node-name: name of a node in the block driver state graph
#
# Since: 2.5
##
{ 'command': 'x-blockdev-insert-medium',
'data': { 'device': 'str',
'data': { '*device': 'str',
'*id': 'str',
'node-name': 'str'} }
@@ -2458,7 +2454,10 @@
# combines blockdev-open-tray, x-blockdev-remove-medium,
# x-blockdev-insert-medium and blockdev-close-tray).
#
# @device: block device name
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device
# (since: 2.8)
#
# @filename: filename of the new image to be loaded
#
@@ -2471,7 +2470,8 @@
# Since: 2.5
##
{ 'command': 'blockdev-change-medium',
'data': { 'device': 'str',
'data': { '*device': 'str',
'*id': 'str',
'filename': 'str',
'*format': 'str',
'*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
+7 -2
View File
@@ -125,7 +125,9 @@
#
# Ejects a device from a removable drive.
#
# @device: The name of the device
# @device: #optional Block device name (deprecated, use @id instead)
#
# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @force: @optional If true, eject regardless of whether the drive is locked.
# If not specified, the default value is false.
@@ -137,7 +139,10 @@
#
# Since: 0.14.0
##
{ 'command': 'eject', 'data': {'device': 'str', '*force': 'bool'} }
{ 'command': 'eject',
'data': { '*device': 'str',
'*id': 'str',
'*force': 'bool' } }
##
# @nbd-server-start:
+30 -4
View File
@@ -28,6 +28,7 @@
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "qemu/help_option.h"
#include "sysemu/block-backend.h"
/*
* Aliases were a bad idea from the start. Let's keep them
@@ -801,7 +802,7 @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
object_unref(OBJECT(dev));
}
void qmp_device_del(const char *id, Error **errp)
static DeviceState *find_device_state(const char *id, Error **errp)
{
Object *obj;
@@ -819,15 +820,40 @@ void qmp_device_del(const char *id, Error **errp)
if (!obj) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", id);
return;
return NULL;
}
if (!object_dynamic_cast(obj, TYPE_DEVICE)) {
error_setg(errp, "%s is not a hotpluggable device", id);
return;
return NULL;
}
qdev_unplug(DEVICE(obj), errp);
return DEVICE(obj);
}
void qmp_device_del(const char *id, Error **errp)
{
DeviceState *dev = find_device_state(id, errp);
if (dev != NULL) {
qdev_unplug(dev, errp);
}
}
BlockBackend *blk_by_qdev_id(const char *id, Error **errp)
{
DeviceState *dev;
BlockBackend *blk;
dev = find_device_state(id, errp);
if (dev == NULL) {
return NULL;
}
blk = blk_by_dev(dev);
if (!blk) {
error_setg(errp, "Device does not have a block device backend");
}
return blk;
}
void qdev_machine_init(void)
+2 -2
View File
@@ -431,8 +431,8 @@ void qmp_change(const char *device, const char *target,
if (strcmp(device, "vnc") == 0) {
qmp_change_vnc(target, has_arg, arg, errp);
} else {
qmp_blockdev_change_medium(device, target, has_arg, arg, false, 0,
errp);
qmp_blockdev_change_medium(true, device, false, NULL, target,
has_arg, arg, false, 0, errp);
}
}
+8 -5
View File
@@ -1,5 +1,10 @@
#!/bin/sh
FORMAT_LIST="raw qcow2 qed vmdk vpc"
if [ "$#" -ne 0 ]; then
FORMAT_LIST="$@"
fi
export QEMU_PROG="$(pwd)/x86_64-softmmu/qemu-system-x86_64"
export QEMU_IMG_PROG="$(pwd)/qemu-img"
export QEMU_IO_PROG="$(pwd)/qemu-io"
@@ -12,10 +17,8 @@ fi
cd tests/qemu-iotests
ret=0
./check -T -nocache -raw || ret=1
./check -T -nocache -qcow2 || ret=1
./check -T -nocache -qed|| ret=1
./check -T -nocache -vmdk|| ret=1
./check -T -nocache -vpc || ret=1
for FMT in $FORMAT_LIST ; do
./check -T -nocache -$FMT || ret=1
done
exit $ret
+32 -39
View File
@@ -782,7 +782,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.vm.launch()
#assemble the quorum block device from the individual files
args = { "options" : { "driver": "quorum", "id": "quorum0",
args = { "options" : { "driver": "quorum", "node-name": "quorum0",
"vote-threshold": 2, "children": [ "img0", "img1", "img2" ] } }
if self.has_quorum():
result = self.vm.qmp("blockdev-add", **args)
@@ -804,13 +804,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name="repair0",
replaces="img1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name="repair0", replaces="img1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {})
self.complete_and_wait(drive="quorum0")
self.complete_and_wait(drive="job0")
self.assert_has_block_node("repair0", quorum_repair_img)
# TODO: a better test requiring some QEMU infrastructure will be added
# to check that this file is really driven by quorum
@@ -824,13 +823,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name="repair0",
replaces="img1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name="repair0", replaces="img1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {})
self.cancel_and_wait(drive="quorum0", force=True)
self.cancel_and_wait(drive="job0", force=True)
# here we check that the last registered quorum file has not been
# swapped out and unref
self.assert_has_block_node(None, quorum_img3)
@@ -842,13 +840,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name="repair0",
replaces="img1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name="repair0", replaces="img1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {})
self.wait_ready_and_cancel(drive="quorum0")
self.wait_ready_and_cancel(drive="job0")
# here we check that the last registered quorum file has not been
# swapped out and unref
self.assert_has_block_node(None, quorum_img3)
@@ -862,13 +859,12 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name="repair0",
replaces="img1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name="repair0", replaces="img1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-pause', device='quorum0')
result = self.vm.qmp('block-job-pause', device='job0')
self.assert_qmp(result, 'return', {})
time.sleep(1)
@@ -879,10 +875,10 @@ class TestRepairQuorum(iotests.QMPTestCase):
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return[0]/offset', offset)
result = self.vm.qmp('block-job-resume', device='quorum0')
result = self.vm.qmp('block-job-resume', device='job0')
self.assert_qmp(result, 'return', {})
self.complete_and_wait(drive="quorum0")
self.complete_and_wait(drive="job0")
self.vm.shutdown()
self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
'target image does not match source after mirroring')
@@ -894,7 +890,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
if iotests.qemu_default_machine != 'pc':
return
result = self.vm.qmp('drive-mirror', device='drive0', # CD-ROM
result = self.vm.qmp('drive-mirror', job_id='job0', device='drive0', # CD-ROM
sync='full',
node_name='repair0',
replaces='img1',
@@ -905,18 +901,18 @@ class TestRepairQuorum(iotests.QMPTestCase):
if not self.has_quorum():
return
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces='img1',
mode='existing',
target=quorum_repair_img, format=iotests.imgfmt)
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name='repair0', replaces='img1',
mode='existing', target=quorum_repair_img,
format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
def test_device_not_found(self):
if not self.has_quorum():
return
result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full',
result = self.vm.qmp('drive-mirror', job_id='job0',
device='nonexistent', sync='full',
node_name='repair0',
replaces='img1',
target=quorum_repair_img, format=iotests.imgfmt)
@@ -926,7 +922,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
if not self.has_quorum():
return
result = self.vm.qmp('drive-mirror', device='quorum0',
result = self.vm.qmp('drive-mirror', device='quorum0', job_id='job0',
node_name='repair0',
replaces='img1',
target=quorum_repair_img, format=iotests.imgfmt)
@@ -936,8 +932,8 @@ class TestRepairQuorum(iotests.QMPTestCase):
if not self.has_quorum():
return
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
replaces='img1',
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', replaces='img1',
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
@@ -945,9 +941,8 @@ class TestRepairQuorum(iotests.QMPTestCase):
if not self.has_quorum():
return
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces='img77',
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name='repair0', replaces='img77',
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
@@ -959,19 +954,17 @@ class TestRepairQuorum(iotests.QMPTestCase):
snapshot_file=quorum_snapshot_file,
snapshot_node_name="snap1");
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces="img1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name='repair0', replaces="img1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
node_name='repair0',
replaces="snap1",
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
sync='full', node_name='repair0', replaces="snap1",
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'return', {})
self.complete_and_wait(drive="quorum0")
self.complete_and_wait('job0')
self.assert_has_block_node("repair0", quorum_repair_img)
# TODO: a better test requiring some QEMU infrastructure will be added
# to check that this file is really driven by quorum
+3 -3
View File
@@ -121,7 +121,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "$IMGFMT",
"id": "disk",
"node-name": "disk",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
@@ -129,13 +129,13 @@ run_qemu <<EOF
}
}
}
{ "execute": "query-block" }
{ "execute": "query-named-block-nodes" }
{ "execute": "device_add",
"arguments": { "driver": "virtio-blk", "drive": "disk",
"id": "virtio0" } }
{ "execute": "device_del", "arguments": { "id": "virtio0" } }
{ "execute": "system_reset" }
{ "execute": "query-block" }
{ "execute": "query-named-block-nodes" }
{ "execute": "quit" }
EOF
+128 -83
View File
@@ -258,49 +258,72 @@ Testing:
{
"return": [
{
"device": "disk",
"locked": false,
"removable": true,
"inserted": {
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 134217728,
"filename": "TEST_DIR/t.qcow2",
"cluster-size": 65536,
"format": "qcow2",
"actual-size": SIZE,
"format-specific": {
"type": "qcow2",
"data": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
},
"dirty-flag": false
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 134217728,
"filename": "TEST_DIR/t.qcow2",
"cluster-size": 65536,
"format": "qcow2",
"actual-size": SIZE,
"format-specific": {
"type": "qcow2",
"data": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
},
"iops_wr": 0,
"ro": false,
"node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
"dirty-flag": false
},
"type": "unknown"
"iops_wr": 0,
"ro": false,
"node-name": "disk",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
{
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 197120,
"filename": "TEST_DIR/t.qcow2",
"format": "file",
"actual-size": SIZE,
"dirty-flag": false
},
"iops_wr": 0,
"ro": false,
"node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "file",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
}
]
}
@@ -319,50 +342,72 @@ Testing:
{
"return": [
{
"io-status": "ok",
"device": "disk",
"locked": false,
"removable": true,
"inserted": {
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 134217728,
"filename": "TEST_DIR/t.qcow2",
"cluster-size": 65536,
"format": "qcow2",
"actual-size": SIZE,
"format-specific": {
"type": "qcow2",
"data": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
},
"dirty-flag": false
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 134217728,
"filename": "TEST_DIR/t.qcow2",
"cluster-size": 65536,
"format": "qcow2",
"actual-size": SIZE,
"format-specific": {
"type": "qcow2",
"data": {
"compat": "1.1",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false
}
},
"iops_wr": 0,
"ro": false,
"node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
"dirty-flag": false
},
"type": "unknown"
"iops_wr": 0,
"ro": false,
"node-name": "disk",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
{
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
"virtual-size": 197120,
"filename": "TEST_DIR/t.qcow2",
"format": "file",
"actual-size": SIZE,
"dirty-flag": false
},
"iops_wr": 0,
"ro": false,
"node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "file",
"iops": 0,
"bps_wr": 0,
"write_threshold": 0,
"encrypted": false,
"bps": 0,
"bps_rd": 0,
"cache": {
"no-flush": false,
"direct": false,
"writeback": true
},
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
}
]
}
+4 -4
View File
@@ -118,7 +118,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "$IMGFMT",
"id": "drive0-debug",
"node-name": "drive0-debug",
"file": {
"driver": "blkdebug",
"image": "drive0",
@@ -159,7 +159,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "blkverify",
"id": "drive0-verify",
"node-name": "drive0-verify",
"test": "drive0",
"raw": {
"driver": "file",
@@ -195,7 +195,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "blkverify",
"id": "drive0-verify",
"node-name": "drive0-verify",
"test": {
"driver": "$IMGFMT",
"file": {
@@ -234,7 +234,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "$IMGFMT",
"id": "drive0-debug",
"node-name": "drive0-debug",
"file": {
"driver": "blkdebug",
"image": "drive0",
+1 -1
View File
@@ -119,7 +119,7 @@ run_qemu <<EOF
"arguments": {
"options": {
"driver": "quorum",
"id": "drive0-quorum",
"node-name": "drive0-quorum",
"vote-threshold": 2,
"children": [
{

Some files were not shown because too many files have changed in this diff Show More