Blame qemu-prevent-cdrom-media-eject-while-device-is-locked.patch

Mark McLoughlin da7d23
From b9052762b5ae94ff7027f0fd0916b1c289bfffef Mon Sep 17 00:00:00 2001
Mark McLoughlin e37615
From: Mark McLoughlin <markmc@redhat.com>
Mark McLoughlin da7d23
Date: Wed, 27 May 2009 10:06:11 +0100
Mark McLoughlin da7d23
Subject: [PATCH 5/7] Prevent CD-ROM media eject while device is locked
Mark McLoughlin e37615
Mark McLoughlin e37615
Section 10.8.25 ("START/STOP UNIT Command") of SFF-8020i states that
Mark McLoughlin e37615
if the device is locked we should refuse to eject if the device is
Mark McLoughlin e37615
locked.
Mark McLoughlin e37615
Mark McLoughlin e37615
ASC_MEDIA_REMOVAL_PREVENTED is the appropriate return in this case.
Mark McLoughlin e37615
Mark McLoughlin e37615
In order to stop itself from ejecting the media it is running from,
Mark McLoughlin e37615
Fedora's installer (anaconda) requires the CDROMEJECT ioctl() to fail
Mark McLoughlin e37615
if the drive has been previously locked.
Mark McLoughlin e37615
Mark McLoughlin e37615
See also https://bugzilla.redhat.com/501412
Mark McLoughlin e37615
Mark McLoughlin da7d23
(cherry picked from commit aea2a33c73f28ecd8f10b242ecadddcc79c1c28b)
Mark McLoughlin da7d23
Mark McLoughlin e37615
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Mark McLoughlin da7d23
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Mark McLoughlin e37615
---
Mark McLoughlin e37615
 block.c  |    9 ++++++++-
Mark McLoughlin e37615
 block.h  |    2 +-
Mark McLoughlin e37615
 hw/ide.c |   26 ++++++++++++++++++--------
Mark McLoughlin e37615
 3 files changed, 27 insertions(+), 10 deletions(-)
Mark McLoughlin e37615
Mark McLoughlin e37615
diff --git a/block.c b/block.c
Mark McLoughlin da7d23
index acb8976..b619147 100644
Mark McLoughlin e37615
--- a/block.c
Mark McLoughlin e37615
+++ b/block.c
Mark McLoughlin da7d23
@@ -1591,11 +1591,15 @@ int bdrv_media_changed(BlockDriverState *bs)
Mark McLoughlin e37615
 /**
Mark McLoughlin e37615
  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
Mark McLoughlin e37615
  */
Mark McLoughlin e37615
-void bdrv_eject(BlockDriverState *bs, int eject_flag)
Mark McLoughlin e37615
+int bdrv_eject(BlockDriverState *bs, int eject_flag)
Mark McLoughlin e37615
 {
Mark McLoughlin e37615
     BlockDriver *drv = bs->drv;
Mark McLoughlin e37615
     int ret;
Mark McLoughlin e37615
 
Mark McLoughlin e37615
+    if (bs->locked) {
Mark McLoughlin e37615
+        return -EBUSY;
Mark McLoughlin e37615
+    }
Mark McLoughlin e37615
+
Mark McLoughlin e37615
     if (!drv || !drv->bdrv_eject) {
Mark McLoughlin e37615
         ret = -ENOTSUP;
Mark McLoughlin e37615
     } else {
Mark McLoughlin da7d23
@@ -1604,7 +1608,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
Mark McLoughlin e37615
     if (ret == -ENOTSUP) {
Mark McLoughlin e37615
         if (eject_flag)
Mark McLoughlin e37615
             bdrv_close(bs);
Mark McLoughlin e37615
+        ret = 0;
Mark McLoughlin e37615
     }
Mark McLoughlin e37615
+
Mark McLoughlin e37615
+    return ret;
Mark McLoughlin e37615
 }
Mark McLoughlin e37615
 
Mark McLoughlin e37615
 int bdrv_is_locked(BlockDriverState *bs)
Mark McLoughlin e37615
diff --git a/block.h b/block.h
Mark McLoughlin da7d23
index 5aef076..a4789b2 100644
Mark McLoughlin e37615
--- a/block.h
Mark McLoughlin e37615
+++ b/block.h
Mark McLoughlin e37615
@@ -136,7 +136,7 @@ int bdrv_is_inserted(BlockDriverState *bs);
Mark McLoughlin e37615
 int bdrv_media_changed(BlockDriverState *bs);
Mark McLoughlin e37615
 int bdrv_is_locked(BlockDriverState *bs);
Mark McLoughlin e37615
 void bdrv_set_locked(BlockDriverState *bs, int locked);
Mark McLoughlin e37615
-void bdrv_eject(BlockDriverState *bs, int eject_flag);
Mark McLoughlin e37615
+int bdrv_eject(BlockDriverState *bs, int eject_flag);
Mark McLoughlin e37615
 void bdrv_set_change_cb(BlockDriverState *bs,
Mark McLoughlin e37615
                         void (*change_cb)(void *opaque), void *opaque);
Mark McLoughlin e37615
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
Mark McLoughlin e37615
diff --git a/hw/ide.c b/hw/ide.c
Mark McLoughlin da7d23
index b2a1288..2c918df 100644
Mark McLoughlin e37615
--- a/hw/ide.c
Mark McLoughlin e37615
+++ b/hw/ide.c
Mark McLoughlin e37615
@@ -359,6 +359,7 @@
Mark McLoughlin e37615
 #define ASC_INCOMPATIBLE_FORMAT              0x30
Mark McLoughlin e37615
 #define ASC_MEDIUM_NOT_PRESENT               0x3a
Mark McLoughlin e37615
 #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED  0x39
Mark McLoughlin e37615
+#define ASC_MEDIA_REMOVAL_PREVENTED          0x53
Mark McLoughlin e37615
 
Mark McLoughlin e37615
 #define CFA_NO_ERROR            0x00
Mark McLoughlin e37615
 #define CFA_MISC_ERROR          0x09
Mark McLoughlin da7d23
@@ -1822,18 +1823,27 @@ static void ide_atapi_cmd(IDEState *s)
Mark McLoughlin e37615
         break;
Mark McLoughlin e37615
     case GPCMD_START_STOP_UNIT:
Mark McLoughlin e37615
         {
Mark McLoughlin e37615
-            int start, eject;
Mark McLoughlin e37615
+            int start, eject, err = 0;
Mark McLoughlin e37615
             start = packet[4] & 1;
Mark McLoughlin e37615
             eject = (packet[4] >> 1) & 1;
Mark McLoughlin e37615
 
Mark McLoughlin e37615
-            if (eject && !start) {
Mark McLoughlin e37615
-                /* eject the disk */
Mark McLoughlin e37615
-                bdrv_eject(s->bs, 1);
Mark McLoughlin e37615
-            } else if (eject && start) {
Mark McLoughlin e37615
-                /* close the tray */
Mark McLoughlin e37615
-                bdrv_eject(s->bs, 0);
Mark McLoughlin e37615
+            if (eject) {
Mark McLoughlin e37615
+                err = bdrv_eject(s->bs, !start);
Mark McLoughlin e37615
+            }
Mark McLoughlin e37615
+
Mark McLoughlin e37615
+            switch (err) {
Mark McLoughlin e37615
+            case 0:
Mark McLoughlin e37615
+                ide_atapi_cmd_ok(s);
Mark McLoughlin e37615
+                break;
Mark McLoughlin e37615
+            case -EBUSY:
Mark McLoughlin e37615
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
Mark McLoughlin e37615
+                                    ASC_MEDIA_REMOVAL_PREVENTED);
Mark McLoughlin e37615
+                break;
Mark McLoughlin e37615
+            default:
Mark McLoughlin e37615
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
Mark McLoughlin e37615
+                                    ASC_MEDIUM_NOT_PRESENT);
Mark McLoughlin e37615
+                break;
Mark McLoughlin e37615
             }
Mark McLoughlin e37615
-            ide_atapi_cmd_ok(s);
Mark McLoughlin e37615
         }
Mark McLoughlin e37615
         break;
Mark McLoughlin e37615
     case GPCMD_MECHANISM_STATUS:
Mark McLoughlin e37615
-- 
Mark McLoughlin e37615
1.6.2.2
Mark McLoughlin e37615