提交 9ec8873e 编写于 作者: K Kevin Wolf

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: NKevin Wolf <kwolf@redhat.com>
Reviewed-by: NEric Blake <eblake@redhat.com>
上级 78645881
...@@ -2844,7 +2844,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict) ...@@ -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: ...@@ -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) ...@@ -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: ...@@ -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) { if (!bs->monitor_list.tqe_prev) {
error_setg(errp, "Block device %s is in use", error_setg(errp, "Node %s is not owned by the monitor",
bdrv_get_device_or_node_name(bs)); bs->node_name);
goto out; goto out;
}
} }
if (blk) { if (bs->refcnt > 1) {
monitor_remove_blk(blk); error_setg(errp, "Block device %s is in use",
blk_unref(blk); bdrv_get_device_or_node_name(bs));
} else { goto out;
QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
} }
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): ...@@ -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 ...@@ -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. ...@@ -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: ...@@ -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: ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 ...@@ -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"}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册