diff mbox

[v3,26/38] blockdev: Add blockdev-open-tray

Message ID 1433360659-1915-27-git-send-email-mreitz@redhat.com
State New
Headers show

Commit Message

Max Reitz June 3, 2015, 7:44 p.m. UTC
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 qapi/block-core.json | 23 +++++++++++++++++++++++
 qmp-commands.hx      | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

Comments

Eric Blake June 3, 2015, 9:24 p.m. UTC | #1
On 06/03/2015 01:44 PM, Max Reitz wrote:
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
>  blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  qapi/block-core.json | 23 +++++++++++++++++++++++
>  qmp-commands.hx      | 39 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 110 insertions(+)
> 

> +++ b/qapi/block-core.json
> @@ -1836,6 +1836,29 @@
>  ##
>  { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
>  
> +##
> +# @blockdev-open-tray:
> +#
> +# Opens a block device's tray. If there is a block driver state tree inserted as
> +# a medium, it will become inaccessible to the guest (but it will remain
> +# associated to the block device, so closing the tray will make it accessible
> +# again).
> +#
> +# If the tray was already open before, this will be a no-op.
> +#
> +# @device: block device name
> +#
> +# @force:  #optional if false (the default), an eject request will be sent to
> +#          the guest if it has locked the tray (and the tray will not be opened
> +#          immediately); if true, the tray will be opened regardless of whether
> +#          it is locked
> +#
> +# Since: 2.3

s/2.3/2.4/ - you'll probably have to make the change throughout the
series (so I won't point it out further)
Max Reitz June 5, 2015, 3:06 p.m. UTC | #2
On 03.06.2015 23:24, Eric Blake wrote:
> On 06/03/2015 01:44 PM, Max Reitz wrote:
>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> ---
>>   blockdev.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   qapi/block-core.json | 23 +++++++++++++++++++++++
>>   qmp-commands.hx      | 39 +++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 110 insertions(+)
>>
>> +++ b/qapi/block-core.json
>> @@ -1836,6 +1836,29 @@
>>   ##
>>   { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
>>   
>> +##
>> +# @blockdev-open-tray:
>> +#
>> +# Opens a block device's tray. If there is a block driver state tree inserted as
>> +# a medium, it will become inaccessible to the guest (but it will remain
>> +# associated to the block device, so closing the tray will make it accessible
>> +# again).
>> +#
>> +# If the tray was already open before, this will be a no-op.
>> +#
>> +# @device: block device name
>> +#
>> +# @force:  #optional if false (the default), an eject request will be sent to
>> +#          the guest if it has locked the tray (and the tray will not be opened
>> +#          immediately); if true, the tray will be opened regardless of whether
>> +#          it is locked
>> +#
>> +# Since: 2.3
> s/2.3/2.4/ - you'll probably have to make the change throughout the
> series (so I won't point it out further)

Oops, right. Thanks.

Max
diff mbox

Patch

diff --git a/blockdev.c b/blockdev.c
index 03d6334..6d9cb12 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2036,6 +2036,54 @@  out:
     aio_context_release(aio_context);
 }
 
+void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
+                            Error **errp)
+{
+    BlockBackend *blk;
+    BlockDriverState *bs;
+    AioContext *aio_context = NULL;
+
+    if (!has_force) {
+        force = false;
+    }
+
+    blk = blk_by_name(device);
+    if (!blk) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    if (!blk_dev_has_removable_media(blk)) {
+        error_setg(errp, "Device '%s' is not removable", device);
+        return;
+    }
+
+    if (blk_dev_is_tray_open(blk)) {
+        return;
+    }
+
+    bs = blk_bs(blk);
+    if (bs) {
+        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;
+        }
+    }
+
+    if (blk_dev_is_medium_locked(blk)) {
+        blk_dev_eject_request(blk, force);
+    } else {
+        blk_dev_change_media_cb(blk, false);
+    }
+
+out:
+    if (aio_context) {
+        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,
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 071b6ee..dfb2b70 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1836,6 +1836,29 @@ 
 ##
 { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
 
+##
+# @blockdev-open-tray:
+#
+# Opens a block device's tray. If there is a block driver state tree inserted as
+# a medium, it will become inaccessible to the guest (but it will remain
+# associated to the block device, so closing the tray will make it accessible
+# again).
+#
+# If the tray was already open before, this will be a no-op.
+#
+# @device: block device name
+#
+# @force:  #optional if false (the default), an eject request will be sent to
+#          the guest if it has locked the tray (and the tray will not be opened
+#          immediately); if true, the tray will be opened regardless of whether
+#          it is locked
+#
+# Since: 2.3
+##
+{ 'command': 'blockdev-open-tray',
+  'data': { 'device': 'str',
+            '*force': 'bool' } }
+
 
 ##
 # @BlockErrorAction
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 324db4b..85f3c6f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3867,6 +3867,45 @@  Example (2):
 EQMP
 
     {
+        .name       = "blockdev-open-tray",
+        .args_type  = "device:s,force:b?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_open_tray,
+    },
+
+SQMP
+blockdev-open-tray
+------------------
+
+Opens a block device's tray. If there is a block driver state tree inserted as a
+medium, it will become inaccessible to the guest (but it will remain associated
+to the block device, so closing the tray will make it accessible again).
+
+If the tray was already open before, this will be a no-op.
+
+Arguments:
+
+- "device": block device name (json-string)
+- "force": if false (the default), an eject request will be sent to the guest if
+           it has locked the tray (and the tray will not be opened immediately);
+           if true, the tray will be opened regardless of whether it is locked
+           (json-bool, optional)
+
+Example:
+
+-> { "execute": "blockdev-open-tray",
+     "arguments": { "device": "ide1-cd0" } }
+
+<- { "timestamp": { "seconds": 1418751016,
+                    "microseconds": 716996 },
+     "event": "DEVICE_TRAY_MOVED",
+     "data": { "device": "ide1-cd0",
+               "tray-open": true } }
+
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "query-named-block-nodes",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_named_block_nodes,