From patchwork Tue Jan 24 18:16:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 137612 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id EE9EBB6F65 for ; Wed, 25 Jan 2012 06:12:12 +1100 (EST) Received: from localhost ([::1]:42048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rplmr-0004FW-5Q for incoming@patchwork.ozlabs.org; Tue, 24 Jan 2012 14:12:09 -0500 Received: from eggs.gnu.org ([140.186.70.92]:41172) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rplmk-0004FE-HA for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:12:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rplmf-0000fW-Nz for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:12:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:31407) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rplmf-0000fB-GC for qemu-devel@nongnu.org; Tue, 24 Jan 2012 14:11:57 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0OJBrrF022072 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 24 Jan 2012 14:11:53 -0500 Received: from doriath.home (ovpn-116-55.ams2.redhat.com [10.36.116.55]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0OJBnbc029151; Tue, 24 Jan 2012 14:11:50 -0500 Date: Tue, 24 Jan 2012 16:16:28 -0200 From: Luiz Capitulino To: qemu-devel Message-ID: <20120124161628.4bf2592c@doriath.home> Organization: Red Hat Mime-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Kevin Wolf , Eric Blake , Markus Armbruster Subject: [Qemu-devel] [PATCH] qmp: add BLOCK_MEDIUM_EJECT event X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Libvirt wants to be notified when the guest ejects a medium, so that it can update its view of the guest. This code has been originally written by Daniel Berrange. It adds the event to IDE and SCSI emulation. Please, note that this only covers guest initiated ejects, that's, the QMP/HMP commands 'eject' and 'change' are not covered. Signed-off-by: Luiz Capitulino Reviewed-by: Eric Blake --- PS: Bugs are mine. QMP/qmp-events.txt | 18 ++++++++++++++++++ block.c | 12 ++++++++++++ block.h | 5 +++++ block_int.h | 3 +++ blockdev.c | 13 +++++++++++++ hw/ide/atapi.c | 1 + hw/scsi-disk.c | 1 + monitor.c | 3 +++ monitor.h | 1 + 9 files changed, 57 insertions(+), 0 deletions(-) diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index af586ec..e414128 100644 --- a/QMP/qmp-events.txt +++ b/QMP/qmp-events.txt @@ -26,6 +26,24 @@ Example: Note: If action is "stop", a STOP event will eventually follow the BLOCK_IO_ERROR event. +BLOCK_MEDIUM_EJECT +------------------ + +Emitted when the guest succeeds ejecting a medium. If the device has a tray, +then this event is emitted whenever the guest opens or closes the tray. + +Data: + +- "device": device name (json-string) +- "ejected": true if the tray has been opened or false if it has been closed + +Example: + +{ "event": "BLOCK_MEDIUM_EJECT", + "data": { "device": "ide1-cd1", + "ejected": true }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + RESET ----- diff --git a/block.c b/block.c index 3f072f6..b25932b 100644 --- a/block.c +++ b/block.c @@ -1998,6 +1998,18 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read) return is_read ? bs->on_read_error : bs->on_write_error; } +void bdrv_dev_set_medium_eject_notify(BlockDriverState *bs, + bdrv_dev_medium_eject_notify_cb cb) +{ + bs->dev_medium_eject_notify_cb = cb; +} + +void bdrv_dev_medium_eject_notify(BlockDriverState *bs, int is_ejected) +{ + assert(bs->dev_medium_eject_notify_cb); + bs->dev_medium_eject_notify_cb(bs, is_ejected); +} + int bdrv_is_read_only(BlockDriverState *bs) { return bs->read_only; diff --git a/block.h b/block.h index 3bd4398..344ca0d 100644 --- a/block.h +++ b/block.h @@ -247,6 +247,11 @@ int bdrv_get_translation_hint(BlockDriverState *bs); void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, BlockErrorAction on_write_error); BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); +typedef void (*bdrv_dev_medium_eject_notify_cb)(BlockDriverState *bs, + int is_ejected); +void bdrv_dev_set_medium_eject_notify(BlockDriverState *bs, + bdrv_dev_medium_eject_notify_cb cb); +void bdrv_dev_medium_eject_notify(BlockDriverState *bs, int is_ejected); int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); diff --git a/block_int.h b/block_int.h index 311bd2a..50c34f6 100644 --- a/block_int.h +++ b/block_int.h @@ -260,6 +260,9 @@ struct BlockDriverState { QTAILQ_ENTRY(BlockDriverState) list; void *private; + /* Callback for medium eject */ + bdrv_dev_medium_eject_notify_cb dev_medium_eject_notify_cb; + QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; }; diff --git a/blockdev.c b/blockdev.c index 1f83c88..71b50fa 100644 --- a/blockdev.c +++ b/blockdev.c @@ -11,6 +11,7 @@ #include "blockdev.h" #include "monitor.h" #include "qerror.h" +#include "qjson.h" #include "qemu-option.h" #include "qemu-config.h" #include "sysemu.h" @@ -237,6 +238,17 @@ static bool do_check_io_limits(BlockIOLimit *io_limits) return true; } +static void on_medium_eject(BlockDriverState *bs, int is_ejected) +{ + QObject *data; + + data = qobject_from_jsonf("{ 'device': %s, 'ejected': %i }", + bdrv_get_device_name(bs), is_ejected); + monitor_protocol_event(QEVENT_BLOCK_MEDIUM_EJECT, data); + + qobject_decref(data); +} + DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) { const char *buf; @@ -503,6 +515,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) QTAILQ_INSERT_TAIL(&drives, dinfo, next); bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error); + bdrv_dev_set_medium_eject_notify(dinfo->bdrv, on_medium_eject); /* disk I/O throttling */ bdrv_set_io_limits(dinfo->bdrv, &io_limits); diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 0adb27b..4b4bc61 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -885,6 +885,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) } bdrv_eject(s->bs, !start); s->tray_open = !start; + bdrv_dev_medium_eject_notify(s->bs, !start); } ide_atapi_cmd_ok(s); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 5d8bf53..35e55f4 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1061,6 +1061,7 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r) } bdrv_eject(s->qdev.conf.bs, !start); s->tray_open = !start; + bdrv_dev_medium_eject_notify(s->qdev.conf.bs, !start); } return 0; } diff --git a/monitor.c b/monitor.c index 187083c..df6b475 100644 --- a/monitor.c +++ b/monitor.c @@ -479,6 +479,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) case QEVENT_SPICE_DISCONNECTED: event_name = "SPICE_DISCONNECTED"; break; + case QEVENT_BLOCK_MEDIUM_EJECT: + event_name = "BLOCK_MEDIUM_EJECT"; + break; default: abort(); break; diff --git a/monitor.h b/monitor.h index 887c472..16fab50 100644 --- a/monitor.h +++ b/monitor.h @@ -36,6 +36,7 @@ typedef enum MonitorEvent { QEVENT_SPICE_CONNECTED, QEVENT_SPICE_INITIALIZED, QEVENT_SPICE_DISCONNECTED, + QEVENT_BLOCK_MEDIUM_EJECT, QEVENT_MAX, } MonitorEvent;