From ce8f3357512a6e17b1bf4f8fd78225d393f98a86 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 21 Mar 2012 09:28:35 -0300 Subject: [RHEL6 qemu-kvm PATCH 4/6] scsi-cd: check ready condition before processing several commands RH-Author: Paolo Bonzini Message-id: <1332322116-12270-5-git-send-email-pbonzini@redhat.com> Patchwork-id: 38775 O-Subject: [RHEL 6.3 qemu-kvm PATCH 4/5] scsi-cd: check ready condition before processing several commands Bugzilla: 803219 RH-Acked-by: Markus Armbruster RH-Acked-by: Laszlo Ersek RH-Acked-by: Gerd Hoffmann Bugzilla: 803219 That this commit fixes a bug is not surprising. What the bug could be 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 (cherry-picked from commit 9bcaf4fe264c507b59ab2e5fc6b2fa9d36f06d44) --- hw/scsi-disk.c | 42 +++++++++++++++++++++++++++++------------- 1 files changed, 29 insertions(+), 13 deletions(-) Signed-off-by: Eduardo Habkost --- 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 faa6a9f..30858a4 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1168,9 +1168,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); @@ -1225,7 +1223,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; @@ -1285,7 +1284,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; @@ -1330,14 +1330,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)); @@ -1372,6 +1364,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: -- 1.7.3.2