diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-03-16 19:11:43 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-03-19 16:35:17 +0100 |
commit | 9bcaf4fe264c507b59ab2e5fc6b2fa9d36f06d44 (patch) | |
tree | e0ef4997657b3d718ee710ea4fe33fcc21af401b /hw | |
parent | 7725d14679c4391391b63f933d604b046ef8adf6 (diff) |
scsi-cd: check ready condition before processing several commands
This commit is more or less obvious. What it caused is less obvious:
SCSI CD drives failed to eject under Linux, though for example the
"change" command worked okay. This happens because of the autoclose
option in the Linux CD-ROM driver.
The actual chain of events is quite complex and somehow involves
udev helpers; the actual command that matters is READ TOC, though
honestly it's not really clear to me how because it should always be
invoked after autoclose, not before.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/scsi-disk.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index add399e97b..7846f45690 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1152,9 +1152,7 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r) outbuf = r->iov.iov_base; switch (req->cmd.buf[0]) { case TEST_UNIT_READY: - if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { - goto not_ready; - } + assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs)); break; case INQUIRY: buflen = scsi_disk_emulate_inquiry(req, outbuf); @@ -1209,7 +1207,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r) memset(outbuf, 0, 8); bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); if (!nb_sectors) { - goto not_ready; + scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); + return -1; } if ((req->cmd.buf[8] & 1) == 0 && req->cmd.lba) { goto illegal_request; @@ -1269,7 +1268,8 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r) memset(outbuf, 0, req->cmd.xfer); bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors); if (!nb_sectors) { - goto not_ready; + scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); + return -1; } if ((req->cmd.buf[14] & 1) == 0 && req->cmd.lba) { goto illegal_request; @@ -1314,14 +1314,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r) buflen = MIN(buflen, req->cmd.xfer); return buflen; -not_ready: - if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { - scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); - } else { - scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY)); - } - return -1; - illegal_request: if (r->req.status == -1) { scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); @@ -1356,6 +1348,30 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) #endif switch (command) { + case INQUIRY: + case MODE_SENSE: + case MODE_SENSE_10: + case RESERVE: + case RESERVE_10: + case RELEASE: + case RELEASE_10: + case START_STOP: + case ALLOW_MEDIUM_REMOVAL: + case GET_CONFIGURATION: + case GET_EVENT_STATUS_NOTIFICATION: + case MECHANISM_STATUS: + case REQUEST_SENSE: + break; + + default: + if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) { + scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); + return 0; + } + break; + } + + switch (command) { case TEST_UNIT_READY: case INQUIRY: case MODE_SENSE: |