mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-01 14:53:54 -06:00
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
3 changed files with 155 additions and 4 deletions
66
blockdev.c
66
blockdev.c
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue