block: Remove BB interface from blockdev-add/del

With this patch, blockdev-add always works on a node level, i.e. it
creates a BDS, but no BB. Consequently, x-blockdev-del doesn't need the
'device' option any more, but 'node-name' becomes mandatory.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Kevin Wolf 2016-09-21 14:56:11 +02:00
parent 7864588150
commit 9ec8873e68
4 changed files with 50 additions and 134 deletions

View File

@ -2844,7 +2844,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
bs = bdrv_find_node(id);
if (bs) {
qmp_x_blockdev_del(false, NULL, true, id, &local_err);
qmp_x_blockdev_del(id, &local_err);
if (local_err) {
error_report_err(local_err);
}
@ -3827,7 +3827,6 @@ out:
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
{
BlockDriverState *bs;
BlockBackend *blk = NULL;
QObject *obj;
Visitor *v = qmp_output_visitor_new(&obj);
QDict *qdict;
@ -3859,37 +3858,21 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
qdict_flatten(qdict);
if (options->has_id) {
blk = blockdev_init(NULL, qdict, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
bs = blk_bs(blk);
} else {
if (!qdict_get_try_str(qdict, "node-name")) {
error_setg(errp, "'id' and/or 'node-name' need to be specified for "
"the root node");
goto fail;
}
bs = bds_tree_init(qdict, errp);
if (!bs) {
goto fail;
}
QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list);
if (!qdict_get_try_str(qdict, "node-name")) {
error_setg(errp, "'node-name' must be specified for the root node");
goto fail;
}
bs = bds_tree_init(qdict, errp);
if (!bs) {
goto fail;
}
QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list);
if (bs && bdrv_key_required(bs)) {
if (blk) {
monitor_remove_blk(blk);
blk_unref(blk);
} else {
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
}
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
error_setg(errp, "blockdev-add doesn't support encrypted devices");
goto fail;
}
@ -3898,81 +3881,42 @@ fail:
visit_free(v);
}
void qmp_x_blockdev_del(bool has_id, const char *id,
bool has_node_name, const char *node_name, Error **errp)
void qmp_x_blockdev_del(const char *node_name, Error **errp)
{
AioContext *aio_context;
BlockBackend *blk;
BlockDriverState *bs;
if (has_id && has_node_name) {
error_setg(errp, "Only one of id and node-name must be specified");
return;
} else if (!has_id && !has_node_name) {
error_setg(errp, "No block device specified");
bs = bdrv_find_node(node_name);
if (!bs) {
error_setg(errp, "Cannot find node %s", node_name);
return;
}
if (has_id) {
/* blk_by_name() never returns a BB that is not owned by the monitor */
blk = blk_by_name(id);
if (!blk) {
error_setg(errp, "Cannot find block backend %s", id);
return;
}
if (blk_legacy_dinfo(blk)) {
error_setg(errp, "Deleting block backend added with drive-add"
" is not supported");
return;
}
if (blk_get_refcnt(blk) > 1) {
error_setg(errp, "Block backend %s is in use", id);
return;
}
bs = blk_bs(blk);
aio_context = blk_get_aio_context(blk);
} else {
blk = NULL;
bs = bdrv_find_node(node_name);
if (!bs) {
error_setg(errp, "Cannot find node %s", node_name);
return;
}
if (bdrv_has_blk(bs)) {
error_setg(errp, "Node %s is in use", node_name);
return;
}
aio_context = bdrv_get_aio_context(bs);
if (bdrv_has_blk(bs)) {
error_setg(errp, "Node %s is in use", node_name);
return;
}
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (bs) {
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
goto out;
}
if (!blk && !QTAILQ_IN_USE(bs, monitor_list)) {
error_setg(errp, "Node %s is not owned by the monitor",
bs->node_name);
goto out;
}
if (bs->refcnt > 1) {
error_setg(errp, "Block device %s is in use",
bdrv_get_device_or_node_name(bs));
goto out;
}
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
goto out;
}
if (blk) {
monitor_remove_blk(blk);
blk_unref(blk);
} else {
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
if (!bs->monitor_list.tqe_prev) {
error_setg(errp, "Node %s is not owned by the monitor",
bs->node_name);
goto out;
}
if (bs->refcnt > 1) {
error_setg(errp, "Block device %s is in use",
bdrv_get_device_or_node_name(bs));
goto out;
}
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
out:
aio_context_release(aio_context);
}

View File

@ -3141,7 +3141,7 @@ Example (2):
"arguments": {
"options": {
"driver": "qcow2",
"id": "my_disk",
"node-name": "my_disk",
"discard": "unmap",
"cache": {
"direct": true,
@ -3168,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
@ -3187,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:
@ -3196,7 +3186,7 @@ Example:
"arguments": {
"options": {
"driver": "qcow2",
"id": "drive0",
"node-name": "node0",
"file": {
"driver": "file",
"filename": "test.qcow2"
@ -3208,7 +3198,7 @@ Example:
<- { "return": {} }
-> { "execute": "x-blockdev-del",
"arguments": { "id": "drive0" }
"arguments": { "node-name": "node0" }
}
<- { "return": {} }

View File

@ -2217,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)
@ -2238,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',
@ -2323,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:

View File

@ -6,7 +6,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "'id' and/or 'node-name' need to be specified for the root node"}}
{"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}