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:
parent
7864588150
commit
9ec8873e68
128
blockdev.c
128
blockdev.c
|
@ -2844,7 +2844,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||||
|
|
||||||
bs = bdrv_find_node(id);
|
bs = bdrv_find_node(id);
|
||||||
if (bs) {
|
if (bs) {
|
||||||
qmp_x_blockdev_del(false, NULL, true, id, &local_err);
|
qmp_x_blockdev_del(id, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
}
|
}
|
||||||
|
@ -3827,7 +3827,6 @@ out:
|
||||||
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockBackend *blk = NULL;
|
|
||||||
QObject *obj;
|
QObject *obj;
|
||||||
Visitor *v = qmp_output_visitor_new(&obj);
|
Visitor *v = qmp_output_visitor_new(&obj);
|
||||||
QDict *qdict;
|
QDict *qdict;
|
||||||
|
@ -3859,37 +3858,21 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
|
||||||
|
|
||||||
qdict_flatten(qdict);
|
qdict_flatten(qdict);
|
||||||
|
|
||||||
if (options->has_id) {
|
if (!qdict_get_try_str(qdict, "node-name")) {
|
||||||
blk = blockdev_init(NULL, qdict, &local_err);
|
error_setg(errp, "'node-name' must be specified for the root node");
|
||||||
if (local_err) {
|
goto fail;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (bs && bdrv_key_required(bs)) {
|
||||||
if (blk) {
|
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
|
||||||
monitor_remove_blk(blk);
|
bdrv_unref(bs);
|
||||||
blk_unref(blk);
|
|
||||||
} else {
|
|
||||||
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
|
|
||||||
bdrv_unref(bs);
|
|
||||||
}
|
|
||||||
error_setg(errp, "blockdev-add doesn't support encrypted devices");
|
error_setg(errp, "blockdev-add doesn't support encrypted devices");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -3898,81 +3881,42 @@ fail:
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_x_blockdev_del(bool has_id, const char *id,
|
void qmp_x_blockdev_del(const char *node_name, Error **errp)
|
||||||
bool has_node_name, const char *node_name, Error **errp)
|
|
||||||
{
|
{
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
BlockBackend *blk;
|
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
|
|
||||||
if (has_id && has_node_name) {
|
bs = bdrv_find_node(node_name);
|
||||||
error_setg(errp, "Only one of id and node-name must be specified");
|
if (!bs) {
|
||||||
return;
|
error_setg(errp, "Cannot find node %s", node_name);
|
||||||
} else if (!has_id && !has_node_name) {
|
|
||||||
error_setg(errp, "No block device specified");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (bdrv_has_blk(bs)) {
|
||||||
if (has_id) {
|
error_setg(errp, "Node %s is in use", node_name);
|
||||||
/* blk_by_name() never returns a BB that is not owned by the monitor */
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
aio_context_acquire(aio_context);
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
if (bs) {
|
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
|
||||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, errp)) {
|
goto out;
|
||||||
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 (blk) {
|
if (!bs->monitor_list.tqe_prev) {
|
||||||
monitor_remove_blk(blk);
|
error_setg(errp, "Node %s is not owned by the monitor",
|
||||||
blk_unref(blk);
|
bs->node_name);
|
||||||
} else {
|
goto out;
|
||||||
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
|
|
||||||
bdrv_unref(bs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
out:
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3141,7 +3141,7 @@ Example (2):
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"options": {
|
"options": {
|
||||||
"driver": "qcow2",
|
"driver": "qcow2",
|
||||||
"id": "my_disk",
|
"node-name": "my_disk",
|
||||||
"discard": "unmap",
|
"discard": "unmap",
|
||||||
"cache": {
|
"cache": {
|
||||||
"direct": true,
|
"direct": true,
|
||||||
|
@ -3168,18 +3168,9 @@ x-blockdev-del
|
||||||
------------
|
------------
|
||||||
Since 2.5
|
Since 2.5
|
||||||
|
|
||||||
Deletes a block device thas has been added using blockdev-add.
|
Deletes a block device that has been added using blockdev-add.
|
||||||
The selected device can be either a block backend or a graph node.
|
The command will fail if the node is attached to a device or is
|
||||||
|
otherwise being used.
|
||||||
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.
|
|
||||||
|
|
||||||
This command is still a work in progress and is considered
|
This command is still a work in progress and is considered
|
||||||
experimental. Stay away from it unless you want to help with its
|
experimental. Stay away from it unless you want to help with its
|
||||||
|
@ -3187,8 +3178,7 @@ development.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- "id": Name of the block backend device to delete (json-string, optional)
|
- "node-name": Name of the graph node to delete (json-string)
|
||||||
- "node-name": Name of the graph node to delete (json-string, optional)
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -3196,7 +3186,7 @@ Example:
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"options": {
|
"options": {
|
||||||
"driver": "qcow2",
|
"driver": "qcow2",
|
||||||
"id": "drive0",
|
"node-name": "node0",
|
||||||
"file": {
|
"file": {
|
||||||
"driver": "file",
|
"driver": "file",
|
||||||
"filename": "test.qcow2"
|
"filename": "test.qcow2"
|
||||||
|
@ -3208,7 +3198,7 @@ Example:
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
-> { "execute": "x-blockdev-del",
|
-> { "execute": "x-blockdev-del",
|
||||||
"arguments": { "id": "drive0" }
|
"arguments": { "node-name": "node0" }
|
||||||
}
|
}
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
|
|
||||||
|
|
|
@ -2217,13 +2217,8 @@
|
||||||
# block devices, independent of the block driver:
|
# block devices, independent of the block driver:
|
||||||
#
|
#
|
||||||
# @driver: block driver name
|
# @driver: block driver name
|
||||||
# @id: #optional id by which the new block device can be referred to.
|
# @node-name: #optional the node name of the new node (Since 2.0).
|
||||||
# This option is only allowed on the top level of blockdev-add.
|
# This option is required 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.
|
|
||||||
# @discard: #optional discard-related options (default: ignore)
|
# @discard: #optional discard-related options (default: ignore)
|
||||||
# @cache: #optional cache-related options
|
# @cache: #optional cache-related options
|
||||||
# @aio: #optional AIO backend (default: threads)
|
# @aio: #optional AIO backend (default: threads)
|
||||||
|
@ -2238,8 +2233,6 @@
|
||||||
##
|
##
|
||||||
{ 'union': 'BlockdevOptions',
|
{ 'union': 'BlockdevOptions',
|
||||||
'base': { 'driver': 'BlockdevDriver',
|
'base': { 'driver': 'BlockdevDriver',
|
||||||
# TODO 'id' is a BB-level option, remove it
|
|
||||||
'*id': 'str',
|
|
||||||
'*node-name': 'str',
|
'*node-name': 'str',
|
||||||
'*discard': 'BlockdevDiscardOptions',
|
'*discard': 'BlockdevDiscardOptions',
|
||||||
'*cache': 'BlockdevCacheOptions',
|
'*cache': 'BlockdevCacheOptions',
|
||||||
|
@ -2323,29 +2316,18 @@
|
||||||
# @x-blockdev-del:
|
# @x-blockdev-del:
|
||||||
#
|
#
|
||||||
# Deletes a block device that has been added using blockdev-add.
|
# Deletes a block device that has been added using blockdev-add.
|
||||||
# The selected device can be either a block backend or a graph node.
|
# The command will fail if the node is attached to a device or is
|
||||||
#
|
# otherwise being used.
|
||||||
# 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.
|
|
||||||
#
|
#
|
||||||
# This command is still a work in progress and is considered
|
# This command is still a work in progress and is considered
|
||||||
# experimental. Stay away from it unless you want to help with its
|
# experimental. Stay away from it unless you want to help with its
|
||||||
# development.
|
# development.
|
||||||
#
|
#
|
||||||
# @id: #optional Name of the block backend device to delete.
|
# @node-name: Name of the graph node to delete.
|
||||||
#
|
|
||||||
# @node-name: #optional Name of the graph node to delete.
|
|
||||||
#
|
#
|
||||||
# Since: 2.5
|
# Since: 2.5
|
||||||
##
|
##
|
||||||
{ 'command': 'x-blockdev-del', 'data': { '*id': 'str', '*node-name': 'str' } }
|
{ 'command': 'x-blockdev-del', 'data': { 'node-name': 'str' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @blockdev-open-tray:
|
# @blockdev-open-tray:
|
||||||
|
|
|
@ -6,7 +6,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
|
||||||
Testing:
|
Testing:
|
||||||
QMP_VERSION
|
QMP_VERSION
|
||||||
{"return": {}}
|
{"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": {}}
|
{"return": {}}
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue