diff options
-rw-r--r-- | QMP/qmp-events.txt | 18 | ||||
-rw-r--r-- | block.c | 84 | ||||
-rw-r--r-- | block.h | 8 | ||||
-rw-r--r-- | block/raw-posix.c | 6 | ||||
-rw-r--r-- | block/raw.c | 2 | ||||
-rw-r--r-- | block_int.h | 2 | ||||
-rw-r--r-- | hw/ide/atapi.c | 7 | ||||
-rw-r--r-- | hw/ide/core.c | 16 | ||||
-rw-r--r-- | hw/scsi-disk.c | 13 | ||||
-rw-r--r-- | hw/virtio-blk.c | 6 | ||||
-rw-r--r-- | monitor.c | 3 | ||||
-rw-r--r-- | monitor.h | 1 |
12 files changed, 104 insertions, 62 deletions
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt index 06cb404837..9286af569d 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. +DEVICE_TRAY_MOVED +----------------- + +It's emitted whenever the tray of a removable device is moved by the guest +or by HMP/QMP commands. + +Data: + +- "device": device name (json-string) +- "tray-open": true if the tray has been opened or false if it has been closed + (json-bool) + +{ "event": "DEVICE_TRAY_MOVED", + "data": { "device": "ide1-cd0", + "tray-open": true + }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + RESET ----- @@ -943,10 +943,59 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, } } +void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, + BlockQMPEventAction action, int is_read) +{ + QObject *data; + const char *action_str; + + switch (action) { + case BDRV_ACTION_REPORT: + action_str = "report"; + break; + case BDRV_ACTION_IGNORE: + action_str = "ignore"; + break; + case BDRV_ACTION_STOP: + action_str = "stop"; + break; + default: + abort(); + } + + data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }", + bdrv->device_name, + action_str, + is_read ? "read" : "write"); + monitor_protocol_event(QEVENT_BLOCK_IO_ERROR, data); + + qobject_decref(data); +} + +static void bdrv_emit_qmp_eject_event(BlockDriverState *bs, bool ejected) +{ + QObject *data; + + data = qobject_from_jsonf("{ 'device': %s, 'tray-open': %i }", + bdrv_get_device_name(bs), ejected); + monitor_protocol_event(QEVENT_DEVICE_TRAY_MOVED, data); + + qobject_decref(data); +} + static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load) { if (bs->dev_ops && bs->dev_ops->change_media_cb) { + bool tray_was_closed = !bdrv_dev_is_tray_open(bs); bs->dev_ops->change_media_cb(bs->dev_opaque, load); + if (tray_was_closed) { + /* tray open */ + bdrv_emit_qmp_eject_event(bs, true); + } + if (load) { + /* tray close */ + bdrv_emit_qmp_eject_event(bs, false); + } } } @@ -2293,35 +2342,6 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, return data.ret; } -void bdrv_mon_event(const BlockDriverState *bdrv, - BlockMonEventAction action, int is_read) -{ - QObject *data; - const char *action_str; - - switch (action) { - case BDRV_ACTION_REPORT: - action_str = "report"; - break; - case BDRV_ACTION_IGNORE: - action_str = "ignore"; - break; - case BDRV_ACTION_STOP: - action_str = "stop"; - break; - default: - abort(); - } - - data = qobject_from_jsonf("{ 'device': %s, 'action': %s, 'operation': %s }", - bdrv->device_name, - action_str, - is_read ? "read" : "write"); - monitor_protocol_event(QEVENT_BLOCK_IO_ERROR, data); - - qobject_decref(data); -} - BlockInfoList *qmp_query_block(Error **errp) { BlockInfoList *head = NULL, *cur_item = NULL; @@ -3609,13 +3629,17 @@ int bdrv_media_changed(BlockDriverState *bs) /** * If eject_flag is TRUE, eject the media. Otherwise, close the tray */ -void bdrv_eject(BlockDriverState *bs, int eject_flag) +void bdrv_eject(BlockDriverState *bs, bool eject_flag) { BlockDriver *drv = bs->drv; if (drv && drv->bdrv_eject) { drv->bdrv_eject(bs, eject_flag); } + + if (bs->device_name[0] != '\0') { + bdrv_emit_qmp_eject_event(bs, eject_flag); + } } /** @@ -85,15 +85,15 @@ typedef enum { typedef enum { BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP -} BlockMonEventAction; +} BlockQMPEventAction; void bdrv_iostatus_enable(BlockDriverState *bs); void bdrv_iostatus_reset(BlockDriverState *bs); void bdrv_iostatus_disable(BlockDriverState *bs); bool bdrv_iostatus_is_enabled(const BlockDriverState *bs); void bdrv_iostatus_set_err(BlockDriverState *bs, int error); -void bdrv_mon_event(const BlockDriverState *bdrv, - BlockMonEventAction action, int is_read); +void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, + BlockQMPEventAction action, int is_read); void bdrv_info_print(Monitor *mon, const QObject *data); void bdrv_info(Monitor *mon, QObject **ret_data); void bdrv_stats_print(Monitor *mon, const QObject *data); @@ -265,7 +265,7 @@ int bdrv_enable_write_cache(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); int bdrv_media_changed(BlockDriverState *bs); void bdrv_lock_medium(BlockDriverState *bs, bool locked); -void bdrv_eject(BlockDriverState *bs, int eject_flag); +void bdrv_eject(BlockDriverState *bs, bool eject_flag); void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size); BlockDriverState *bdrv_find(const char *name); BlockDriverState *bdrv_next(BlockDriverState *bs); diff --git a/block/raw-posix.c b/block/raw-posix.c index 2ee5d690e9..2d1bc13484 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -994,7 +994,7 @@ static int floppy_media_changed(BlockDriverState *bs) return ret; } -static void floppy_eject(BlockDriverState *bs, int eject_flag) +static void floppy_eject(BlockDriverState *bs, bool eject_flag) { BDRVRawState *s = bs->opaque; int fd; @@ -1084,7 +1084,7 @@ static int cdrom_is_inserted(BlockDriverState *bs) return 0; } -static void cdrom_eject(BlockDriverState *bs, int eject_flag) +static void cdrom_eject(BlockDriverState *bs, bool eject_flag) { BDRVRawState *s = bs->opaque; @@ -1194,7 +1194,7 @@ static int cdrom_is_inserted(BlockDriverState *bs) return raw_getlength(bs) > 0; } -static void cdrom_eject(BlockDriverState *bs, int eject_flag) +static void cdrom_eject(BlockDriverState *bs, bool eject_flag) { BDRVRawState *s = bs->opaque; diff --git a/block/raw.c b/block/raw.c index 6098070d65..1cdac0ccdc 100644 --- a/block/raw.c +++ b/block/raw.c @@ -61,7 +61,7 @@ static int raw_media_changed(BlockDriverState *bs) return bdrv_media_changed(bs->file); } -static void raw_eject(BlockDriverState *bs, int eject_flag) +static void raw_eject(BlockDriverState *bs, bool eject_flag) { bdrv_eject(bs->file, eject_flag); } diff --git a/block_int.h b/block_int.h index 7946cf66a1..04f4b836ca 100644 --- a/block_int.h +++ b/block_int.h @@ -197,7 +197,7 @@ struct BlockDriver { /* removable device specific */ int (*bdrv_is_inserted)(BlockDriverState *bs); int (*bdrv_media_changed)(BlockDriverState *bs); - void (*bdrv_eject)(BlockDriverState *bs, int eject_flag); + void (*bdrv_eject)(BlockDriverState *bs, bool eject_flag); void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); /* to control generic scsi devices */ diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 0adb27b799..5919cf52d8 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -883,8 +883,11 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); return; } - bdrv_eject(s->bs, !start); - s->tray_open = !start; + + if (s->tray_open != !start) { + bdrv_eject(s->bs, !start); + s->tray_open = !start; + } } ide_atapi_cmd_ok(s); diff --git a/hw/ide/core.c b/hw/ide/core.c index 56b219b504..ce570a7ce5 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -519,7 +519,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) BlockErrorAction action = bdrv_get_on_error(s->bs, is_read); if (action == BLOCK_ERR_IGNORE) { - bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } @@ -527,7 +527,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) || action == BLOCK_ERR_STOP_ANY) { s->bus->dma->ops->set_unit(s->bus->dma, s->unit); s->bus->error_status = op; - bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); bdrv_iostatus_set_err(s->bs, error); } else { @@ -537,7 +537,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) } else { ide_rw_error(s); } - bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read); } return 1; @@ -2077,15 +2077,6 @@ static bool ide_drive_pio_state_needed(void *opaque) || (s->bus->error_status & BM_STATUS_PIO_RETRY); } -static int ide_tray_state_post_load(void *opaque, int version_id) -{ - IDEState *s = opaque; - - bdrv_eject(s->bs, s->tray_open); - bdrv_lock_medium(s->bs, s->tray_locked); - return 0; -} - static bool ide_tray_state_needed(void *opaque) { IDEState *s = opaque; @@ -2125,7 +2116,6 @@ static const VMStateDescription vmstate_ide_tray_state = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .post_load = ide_tray_state_post_load, .fields = (VMStateField[]) { VMSTATE_BOOL(tray_open, IDEState), VMSTATE_BOOL(tray_locked, IDEState), diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 4101a59d34..add399e97b 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -291,14 +291,14 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) BlockErrorAction action = bdrv_get_on_error(s->qdev.conf.bs, is_read); if (action == BLOCK_ERR_IGNORE) { - bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read); + bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE, is_read); return 0; } if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) || action == BLOCK_ERR_STOP_ANY) { - bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read); + bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); bdrv_iostatus_set_err(s->qdev.conf.bs, error); scsi_req_retry(&r->req); @@ -317,7 +317,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error) scsi_check_condition(r, SENSE_CODE(IO_ERROR)); break; } - bdrv_mon_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read); + bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_REPORT, is_read); } return 1; } @@ -1116,8 +1116,11 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r) : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED)); return -1; } - bdrv_eject(s->qdev.conf.bs, !start); - s->tray_open = !start; + + if (s->tray_open != !start) { + bdrv_eject(s->qdev.conf.bs, !start); + s->tray_open = !start; + } } return 0; } diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index a5a439668b..49990f8efe 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -69,7 +69,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, VirtIOBlock *s = req->dev; if (action == BLOCK_ERR_IGNORE) { - bdrv_mon_event(s->bs, BDRV_ACTION_IGNORE, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } @@ -77,14 +77,14 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, || action == BLOCK_ERR_STOP_ANY) { req->next = s->rq; s->rq = req; - bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); bdrv_iostatus_set_err(s->bs, error); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); g_free(req); - bdrv_mon_event(s->bs, BDRV_ACTION_REPORT, is_read); + bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read); } return 1; @@ -485,6 +485,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) case QEVENT_BLOCK_JOB_CANCELLED: event_name = "BLOCK_JOB_CANCELLED"; break; + case QEVENT_DEVICE_TRAY_MOVED: + event_name = "DEVICE_TRAY_MOVED"; + break; default: abort(); break; @@ -38,6 +38,7 @@ typedef enum MonitorEvent { QEVENT_SPICE_DISCONNECTED, QEVENT_BLOCK_JOB_COMPLETED, QEVENT_BLOCK_JOB_CANCELLED, + QEVENT_DEVICE_TRAY_MOVED, QEVENT_MAX, } MonitorEvent; |