From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:39156) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RNSP1-0000mM-RI for qemu-devel@nongnu.org; Mon, 07 Nov 2011 11:50:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RNSOx-0004Sq-Dp for qemu-devel@nongnu.org; Mon, 07 Nov 2011 11:50:31 -0500 Received: from mail-qw0-f45.google.com ([209.85.216.45]:59809) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RNSOx-0004Sl-AQ for qemu-devel@nongnu.org; Mon, 07 Nov 2011 11:50:27 -0500 Received: by qadz3 with SMTP id z3so806598qad.4 for ; Mon, 07 Nov 2011 08:50:26 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 7 Nov 2011 17:50:13 +0100 Message-Id: <1320684613-19540-1-git-send-email-pbonzini@redhat.com> In-reply-to: <1319540020-32484-7-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 6/8 v2] block: add eject request callback List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, armbru@redhat.com Recent versions of udev always keep the tray locked so that the kernel can observe "eject request" events (aka tray button presses) even on discs that aren't mounted. Add support for these events in the ATAPI and SCSI cd drive device models. To let management cope with the behavior of udev, an event should also be added for "tray opened/closed". This way, after issuing an "eject" command, management can poll until the guests actually reacts to the command. They can then issue the "change" command after the tray has been opened, or try with "eject -f" after a (configurable?) timeout. However, with this patch and the corresponding support in the device models, at least it is possible to do a manual two-step eject+change sequence. Signed-off-by: Paolo Bonzini --- v1->v2: do not change the behavior of eject -f. block.c | 7 +++++++ block.h | 8 ++++++++ blockdev.c | 10 ++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 0568df2..e847738 100644 --- a/block.c +++ b/block.c @@ -816,6 +816,13 @@ bool bdrv_dev_has_removable_media(BlockDriverState *bs) return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb); } +void bdrv_dev_eject_request(BlockDriverState *bs, bool force) +{ + if (bs->dev_ops && bs->dev_ops->eject_request_cb) { + bs->dev_ops->eject_request_cb(bs->dev_opaque, force); + } +} + bool bdrv_dev_is_tray_open(BlockDriverState *bs) { if (bs->dev_ops && bs->dev_ops->is_tray_open) { diff --git a/block.h b/block.h index 38cd748..38fd0f6 100644 --- a/block.h +++ b/block.h @@ -39,6 +39,15 @@ typedef struct BlockDevOps { */ void (*change_media_cb)(void *opaque, bool load); /* + * Runs when an eject request is issued from the monitor, the tray + * is closed, and the medium is locked. + * Device models that do not implement is_medium_locked will not need + * this callback. Device models that can lock the medium or tray might + * want to implement the callback and unlock the tray when "force" is + * true, even if they do not support eject requests. + */ + void (*eject_request_cb)(void *opaque, bool force); + /* * Is the virtual tray open? * Device models implement this only when the device has a tray. */ @@ -111,6 +118,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev); void *bdrv_get_attached_dev(BlockDriverState *bs); void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, void *opaque); +void bdrv_dev_eject_request(BlockDriverState *bs, bool force); bool bdrv_dev_has_removable_media(BlockDriverState *bs); bool bdrv_dev_is_tray_open(BlockDriverState *bs); bool bdrv_dev_is_medium_locked(BlockDriverState *bs); diff --git a/blockdev.c b/blockdev.c index 0827bf7..2228186 100644 --- a/blockdev.c +++ b/blockdev.c @@ -635,10 +635,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force) qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs)); return -1; } - if (!force && !bdrv_dev_is_tray_open(bs) - && bdrv_dev_is_medium_locked(bs)) { - qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); - return -1; + if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { + bdrv_dev_eject_request(bs, force); + if (!force) { + qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); + return -1; + } } bdrv_close(bs); return 0; -- 1.7.7.1