aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/blockdev.c b/blockdev.c
index b6fa210249..40e4e6fc6f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2281,16 +2281,29 @@ exit:
block_job_txn_unref(block_job_txn);
}
+static int do_open_tray(const char *device, bool force, Error **errp);
+
void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
{
Error *local_err = NULL;
+ int rc;
+
+ if (!has_force) {
+ force = false;
+ }
- qmp_blockdev_open_tray(device, has_force, force, &local_err);
+ rc = do_open_tray(device, force, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
+ if (rc == EINPROGRESS) {
+ error_setg(errp, "Device '%s' is locked and force was not specified, "
+ "wait for tray to open and try again", device);
+ return;
+ }
+
qmp_x_blockdev_remove_medium(device, errp);
}
@@ -2318,35 +2331,36 @@ void qmp_block_passwd(bool has_device, const char *device,
aio_context_release(aio_context);
}
-void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
- Error **errp)
+/**
+ * returns -errno on fatal error, +errno for non-fatal situations.
+ * errp will always be set when the return code is negative.
+ * May return +ENOSYS if the device has no tray,
+ * or +EINPROGRESS if the tray is locked and the guest has been notified.
+ */
+static int do_open_tray(const char *device, bool force, Error **errp)
{
BlockBackend *blk;
bool locked;
- if (!has_force) {
- force = false;
- }
-
blk = blk_by_name(device);
if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
- return;
+ return -ENODEV;
}
if (!blk_dev_has_removable_media(blk)) {
error_setg(errp, "Device '%s' is not removable", device);
- return;
+ return -ENOTSUP;
}
if (!blk_dev_has_tray(blk)) {
/* Ignore this command on tray-less devices */
- return;
+ return ENOSYS;
}
if (blk_dev_is_tray_open(blk)) {
- return;
+ return 0;
}
locked = blk_dev_is_medium_locked(blk);
@@ -2357,6 +2371,21 @@ void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
if (!locked || force) {
blk_dev_change_media_cb(blk, false);
}
+
+ if (locked && !force) {
+ return EINPROGRESS;
+ }
+
+ return 0;
+}
+
+void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
+ Error **errp)
+{
+ if (!has_force) {
+ force = false;
+ }
+ do_open_tray(device, force, errp);
}
void qmp_blockdev_close_tray(const char *device, Error **errp)