blockdev: Add blockdev-remove-medium

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Max Reitz 2015-10-26 21:39:10 +01:00 committed by Kevin Wolf
parent abaaf59d24
commit 2814f67271
3 changed files with 112 additions and 0 deletions

View file

@ -2147,6 +2147,57 @@ void qmp_blockdev_close_tray(const char *device, Error **errp)
blk_dev_change_media_cb(blk, true);
}
void qmp_blockdev_remove_medium(const char *device, Error **errp)
{
BlockBackend *blk;
BlockDriverState *bs;
AioContext *aio_context;
bool has_device;
blk = blk_by_name(device);
if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
return;
}
/* For BBs without a device, we can exchange the BDS tree at will */
has_device = blk_get_attached_dev(blk);
if (has_device && !blk_dev_has_removable_media(blk)) {
error_setg(errp, "Device '%s' is not removable", device);
return;
}
if (has_device && !blk_dev_is_tray_open(blk)) {
error_setg(errp, "Tray of device '%s' is not open", device);
return;
}
bs = blk_bs(blk);
if (!bs) {
return;
}
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
goto out;
}
/* This follows the convention established by bdrv_make_anon() */
if (bs->device_list.tqe_prev) {
QTAILQ_REMOVE(&bdrv_states, bs, device_list);
bs->device_list.tqe_prev = NULL;
}
blk_remove_bs(blk);
out:
aio_context_release(aio_context);
}
/* throttling disk I/O limits */
void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
int64_t bps_wr,

View file

@ -1924,6 +1924,22 @@
{ 'command': 'blockdev-close-tray',
'data': { 'device': 'str' } }
##
# @blockdev-remove-medium:
#
# Removes a medium (a block driver state tree) from a block device. That block
# device's tray must currently be open (unless there is no attached guest
# device).
#
# If the tray is open and there is no medium inserted, this will be a no-op.
#
# @device: block device name
#
# Since: 2.5
##
{ 'command': 'blockdev-remove-medium',
'data': { 'device': 'str' } }
##
# @BlockErrorAction

View file

@ -4035,6 +4035,51 @@ Example:
<- { "return": {} }
EQMP
{
.name = "blockdev-remove-medium",
.args_type = "device:s",
.mhandler.cmd_new = qmp_marshal_blockdev_remove_medium,
},
SQMP
blockdev-remove-medium
----------------------
Removes a medium (a block driver state tree) from a block device. That block
device's tray must currently be open (unless there is no attached guest device).
If the tray is open and there is no medium inserted, this will be a no-op.
Arguments:
- "device": block device name (json-string)
Example:
-> { "execute": "blockdev-remove-medium",
"arguments": { "device": "ide1-cd0" } }
<- { "error": { "class": "GenericError",
"desc": "Tray of device 'ide1-cd0' is not open" } }
-> { "execute": "blockdev-open-tray",
"arguments": { "device": "ide1-cd0" } }
<- { "timestamp": { "seconds": 1418751627,
"microseconds": 549958 },
"event": "DEVICE_TRAY_MOVED",
"data": { "device": "ide1-cd0",
"tray-open": true } }
<- { "return": {} }
-> { "execute": "blockdev-remove-medium",
"arguments": { "device": "ide1-cd0" } }
<- { "return": {} }
EQMP
{