From ce8f3357512a6e17b1bf4f8fd78225d393f98a86 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
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 <pbonzini@redhat.com>
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 <armbru@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>

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 <pbonzini@redhat.com>
(cherry-picked from commit 9bcaf4fe264c507b59ab2e5fc6b2fa9d36f06d44)
---
 hw/scsi-disk.c |   42 +++++++++++++++++++++++++++++-------------
 1 files changed, 29 insertions(+), 13 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 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

