From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56809) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zw9db-0002bh-7g for qemu-devel@nongnu.org; Tue, 10 Nov 2015 09:11:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zw9dW-0004Yr-KU for qemu-devel@nongnu.org; Tue, 10 Nov 2015 09:11:07 -0500 From: Kevin Wolf Date: Tue, 10 Nov 2015 15:09:38 +0100 Message-Id: <1447164580-31094-39-git-send-email-kwolf@redhat.com> In-Reply-To: <1447164580-31094-1-git-send-email-kwolf@redhat.com> References: <1447164580-31094-1-git-send-email-kwolf@redhat.com> Subject: [Qemu-devel] [PULL v2 38/40] block: Add 'x-blockdev-del' QMP command List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-block@nongnu.org Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Alberto Garcia 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 Reviewed-by: Max Reitz Message-id: 6cfc148c77aca1da942b094d811bfa3fcf7ac7bb.1446475331.git.berto@igalia.com Signed-off-by: Max Reitz --- blockdev.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ qapi/block-core.json | 32 +++++++++++++++++++++++-- qmp-commands.hx | 61 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 3197791..8607df9 100644 --- a/blockdev.c +++ b/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; diff --git a/qapi/block-core.json b/qapi/block-core.json index 083d2cd..470e86c 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -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 # @@ -1905,6 +1905,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: # # Opens a block device's tray. If there is a block driver state tree inserted as diff --git a/qmp-commands.hx b/qmp-commands.hx index bd4d38f..658e7da 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3927,8 +3927,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: @@ -3974,6 +3974,63 @@ Example (2): 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 + + { .name = "blockdev-open-tray", .args_type = "device:s,force:b?", .mhandler.cmd_new = qmp_marshal_blockdev_open_tray, -- 1.8.3.1