This is the sister command to blockdev-add. In Fam's example he uses the drive_del HMP command to clean up but when trying to do this via libvirt it doesn't work. This command seems to be needed in order to perform proper cleanup. Signed-off-by: Ian Main <imain@xxxxxxxxxx> --- blockdev.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- qapi-schema.json | 11 +++++++++++ qmp-commands.hx | 30 ++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/blockdev.c b/blockdev.c index 7372721..d6a139a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1733,21 +1733,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, } } -int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) +/* This is called by both do_drive_del() and qmp_blockdev_delete */ +static int drive_del_core(BlockDriverState *bs) { - const char *id = qdict_get_str(qdict, "id"); - BlockDriverState *bs; - - bs = bdrv_find(id); - if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, id); - return -1; - } - if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, NULL)) { - qerror_report(QERR_DEVICE_IN_USE, id); - return -1; - } - /* quiesce block driver; prevent further io */ bdrv_drain_all(); bdrv_flush(bs); @@ -1771,6 +1759,25 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) return 0; } +int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *id = qdict_get_str(qdict, "id"); + BlockDriverState *bs; + + bs = bdrv_find(id); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, id); + return -1; + } + + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, NULL)) { + qerror_report(QERR_DEVICE_IN_USE, id); + return -1; + } + + return drive_del_core(bs); +} + void qmp_block_resize(bool has_device, const char *device, bool has_node_name, const char *node_name, int64_t size, Error **errp) @@ -2386,6 +2393,23 @@ fail: qmp_output_visitor_cleanup(ov); } +void qmp_blockdev_delete(const char *device, Error **errp) +{ + BlockDriverState *bs; + + bs = bdrv_find(device); + if (!bs) { + error_setg(errp, "Block device not found"); + return; + } + + if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, NULL)) { + return; + } + + drive_del_core(bs); +} + static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) { BlockJobInfoList **prev = opaque; diff --git a/qapi-schema.json b/qapi-schema.json index d22651c..ff97987 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4469,3 +4469,14 @@ # Since: 1.7 ## { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } } + +## +# @blockdev-delete: +# +# Delete a block device. +# +# @device: Identifier for the block device to be deleted. +# +# Since: 2.0 +## +{ 'command': 'blockdev-delete', 'data': { 'device': 'str' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index c3ee46a..be3552a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3442,6 +3442,36 @@ Example (2): EQMP { + .name = "blockdev-delete", + .args_type = "device:s", + .mhandler.cmd_new = qmp_marshal_input_blockdev_delete, + }, + +SQMP +blockdev-delete +------------ + +Remove host block device. The result is that guest generated IO is no +longer submitted against the host device underlying the disk. Once a +drive has been deleted, the QEMU Block layer returns -EIO which results +in IO errors in the guest for applications that are reading/writing to +the device. These errors are always reported to the guest, regardless +of the drive's error actions (drive options rerror, werror). + +Arguments: + +- "device": Identifier of the block device (json-string) + +Example (1): + +-> { "execute": "blockdev-snapshot-delete-internal-sync", + "arguments": { "device": "target0" } + } +<- { "return": {} } + +EQMP + + { .name = "query-named-block-nodes", .args_type = "", .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes, -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list