diff options
author | Max Reitz <mreitz@redhat.com> | 2015-10-26 21:39:10 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2015-11-11 16:22:47 +0100 |
commit | 2814f67271bce537f29c6a7832f89fd4f1cdaa1a (patch) | |
tree | d94904f6f9dbe9f8a4a3f6941cb076977f6b35ab /blockdev.c | |
parent | abaaf59d245b6984644497b6745f88912c715c39 (diff) | |
download | qemu-2814f67271bce537f29c6a7832f89fd4f1cdaa1a.tar.gz qemu-2814f67271bce537f29c6a7832f89fd4f1cdaa1a.tar.bz2 qemu-2814f67271bce537f29c6a7832f89fd4f1cdaa1a.zip |
blockdev: Add blockdev-remove-medium
Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'blockdev.c')
-rw-r--r-- | blockdev.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/blockdev.c b/blockdev.c index cb8a2f095b..25635e3597 100644 --- a/blockdev.c +++ b/blockdev.c @@ -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, |