mvadkert / rpms / qemu

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