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:
parent
f636ae85f3
commit
81b936ae70
66
blockdev.c
66
blockdev.c
@ -3479,6 +3479,72 @@ fail:
|
|||||||
qmp_output_visitor_cleanup(ov);
|
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 *qmp_query_block_jobs(Error **errp)
|
||||||
{
|
{
|
||||||
BlockJobInfoList *head = NULL, **p_next = &head;
|
BlockJobInfoList *head = NULL, **p_next = &head;
|
||||||
|
@ -1895,8 +1895,8 @@
|
|||||||
# level and no BlockBackend will be created.
|
# level and no BlockBackend will be created.
|
||||||
#
|
#
|
||||||
# This command is still a work in progress. It doesn't support all
|
# This command is still a work in progress. It doesn't support all
|
||||||
# block drivers, it lacks a matching blockdev-del, and more. Stay
|
# block drivers among other things. Stay away from it unless you want
|
||||||
# away from it unless you want to help with its development.
|
# to help with its development.
|
||||||
#
|
#
|
||||||
# @options: block device options for the new device
|
# @options: block device options for the new device
|
||||||
#
|
#
|
||||||
@ -1904,6 +1904,34 @@
|
|||||||
##
|
##
|
||||||
{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
|
{ '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:
|
# @blockdev-open-tray:
|
||||||
#
|
#
|
||||||
|
@ -3946,8 +3946,8 @@ blockdev-add
|
|||||||
Add a block device.
|
Add a block device.
|
||||||
|
|
||||||
This command is still a work in progress. It doesn't support all
|
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
|
block drivers among other things. Stay away from it unless you want
|
||||||
from it unless you want to help with its development.
|
to help with its development.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -3990,6 +3990,63 @@ Example (2):
|
|||||||
|
|
||||||
<- { "return": {} }
|
<- { "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
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user