block: Add 'x-blockdev-del' QMP command

This command is still experimental, hence the name.

This is the companion to 'blockdev-add'. It allows deleting a
BlockBackend with its associated BlockDriverState tree, or a
BlockDriverState that is not attached to any backend.

In either case, the command fails if the reference count is greater
than 1 or the BlockDriverState has any parents.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 6cfc148c77aca1da942b094d811bfa3fcf7ac7bb.1446475331.git.berto@igalia.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Alberto Garcia 2015-11-02 16:51:55 +02:00 committed by Max Reitz
parent f636ae85f3
commit 81b936ae70
3 changed files with 155 additions and 4 deletions

View File

@ -3479,6 +3479,72 @@ fail:
qmp_output_visitor_cleanup(ov);
}
void qmp_x_blockdev_del(bool has_id, const char *id,
bool has_node_name, 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");
return;
}
if (has_id) {
blk = blk_by_name(id);
if (!blk) {
error_setg(errp, "Cannot find block backend %s", id);
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 {
bs = bdrv_find_node(node_name);
if (!bs) {
error_setg(errp, "Cannot find node %s", node_name);
return;
}
blk = bs->blk;
if (blk) {
error_setg(errp, "Node %s is in use by %s",
node_name, blk_name(blk));
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 (bs->refcnt > 1 || !QLIST_EMPTY(&bs->parents)) {
error_setg(errp, "Block device %s is in use",
bdrv_get_device_or_node_name(bs));
goto out;
}
}
if (blk) {
blk_unref(blk);
} else {
bdrv_unref(bs);
}
out:
aio_context_release(aio_context);
}
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
{
BlockJobInfoList *head = NULL, **p_next = &head;

View File

@ -1895,8 +1895,8 @@
# level and no BlockBackend will be created.
#
# This command is still a work in progress. It doesn't support all
# block drivers, it lacks a matching blockdev-del, and more. Stay
# away from it unless you want to help with its development.
# block drivers among other things. Stay away from it unless you want
# to help with its development.
#
# @options: block device options for the new device
#
@ -1904,6 +1904,34 @@
##
{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
##
# @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.
#
# 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.
#
# Since: 2.5
##
{ 'command': 'x-blockdev-del', 'data': { '*id': 'str', '*node-name': 'str' } }
##
# @blockdev-open-tray:
#

View File

@ -3946,8 +3946,8 @@ blockdev-add
Add a block device.
This command is still a work in progress. It doesn't support all
block drivers, it lacks a matching blockdev-del, and more. Stay away
from it unless you want to help with its development.
block drivers among other things. Stay away from it unless you want
to help with its development.
Arguments:
@ -3990,6 +3990,63 @@ Example (2):
<- { "return": {} }
EQMP
{
.name = "x-blockdev-del",
.args_type = "id:s?,node-name:s?",
.mhandler.cmd_new = qmp_marshal_x_blockdev_del,
},
SQMP
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.
This command is still a work in progress and is considered
experimental. Stay away from it unless you want to help with its
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)
Example:
-> { "execute": "blockdev-add",
"arguments": {
"options": {
"driver": "qcow2",
"id": "drive0",
"file": {
"driver": "file",
"filename": "test.qcow2"
}
}
}
}
<- { "return": {} }
-> { "execute": "x-blockdev-del",
"arguments": { "id": "drive0" }
}
<- { "return": {} }
EQMP
{