]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
Prevent CD-ROM media eject while device is locked
authorMark McLoughlin <markmc@redhat.com>
Wed, 27 May 2009 09:06:11 +0000 (10:06 +0100)
committerAnthony Liguori <aliguori@us.ibm.com>
Tue, 16 Jun 2009 22:46:59 +0000 (17:46 -0500)
Section 10.8.25 ("START/STOP UNIT Command") of SFF-8020i states that
if the device is locked we should refuse to eject if the device is
locked.

ASC_MEDIA_REMOVAL_PREVENTED is the appropriate return in this case.

In order to stop itself from ejecting the media it is running from,
Fedora's installer (anaconda) requires the CDROMEJECT ioctl() to fail
if the drive has been previously locked.

See also https://bugzilla.redhat.com/501412

(cherry picked from commit aea2a33c73f28ecd8f10b242ecadddcc79c1c28b)

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
block.c
block.h
hw/ide.c

diff --git a/block.c b/block.c
index b68a8da09c1c80fc05ec1b1bd45830bf950b0027..e5cd23d34a376be0875ff1b1bd671068df5b11f7 100644 (file)
--- a/block.c
+++ b/block.c
@@ -1664,11 +1664,15 @@ int bdrv_media_changed(BlockDriverState *bs)
 /**
  * If eject_flag is TRUE, eject the media. Otherwise, close the tray
  */
-void bdrv_eject(BlockDriverState *bs, int eject_flag)
+int bdrv_eject(BlockDriverState *bs, int eject_flag)
 {
     BlockDriver *drv = bs->drv;
     int ret;
 
+    if (bs->locked) {
+        return -EBUSY;
+    }
+
     if (!drv || !drv->bdrv_eject) {
         ret = -ENOTSUP;
     } else {
@@ -1677,7 +1681,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
     if (ret == -ENOTSUP) {
         if (eject_flag)
             bdrv_close(bs);
+        ret = 0;
     }
+
+    return ret;
 }
 
 int bdrv_is_locked(BlockDriverState *bs)
diff --git a/block.h b/block.h
index 979781a12e8f69fd72f21950e258f4a9f6aa5ae4..e1070e9c344325af37ef5413476958d946e8262f 100644 (file)
--- a/block.h
+++ b/block.h
@@ -132,7 +132,7 @@ int bdrv_is_inserted(BlockDriverState *bs);
 int bdrv_media_changed(BlockDriverState *bs);
 int bdrv_is_locked(BlockDriverState *bs);
 void bdrv_set_locked(BlockDriverState *bs, int locked);
-void bdrv_eject(BlockDriverState *bs, int eject_flag);
+int bdrv_eject(BlockDriverState *bs, int eject_flag);
 void bdrv_set_change_cb(BlockDriverState *bs,
                         void (*change_cb)(void *opaque), void *opaque);
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
index 6ad1d081a6d41e6e3ce2ef3a5c1da23d8464734b..9b93e7f678de9f1e149932fce46769f784dc9f49 100644 (file)
--- a/hw/ide.c
+++ b/hw/ide.c
 #define ASC_INCOMPATIBLE_FORMAT              0x30
 #define ASC_MEDIUM_NOT_PRESENT               0x3a
 #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED  0x39
+#define ASC_MEDIA_REMOVAL_PREVENTED          0x53
 
 #define CFA_NO_ERROR            0x00
 #define CFA_MISC_ERROR          0x09
@@ -1818,18 +1819,27 @@ static void ide_atapi_cmd(IDEState *s)
         break;
     case GPCMD_START_STOP_UNIT:
         {
-            int start, eject;
+            int start, eject, err = 0;
             start = packet[4] & 1;
             eject = (packet[4] >> 1) & 1;
 
-            if (eject && !start) {
-                /* eject the disk */
-                bdrv_eject(s->bs, 1);
-            } else if (eject && start) {
-                /* close the tray */
-                bdrv_eject(s->bs, 0);
+            if (eject) {
+                err = bdrv_eject(s->bs, !start);
+            }
+
+            switch (err) {
+            case 0:
+                ide_atapi_cmd_ok(s);
+                break;
+            case -EBUSY:
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                    ASC_MEDIA_REMOVAL_PREVENTED);
+                break;
+            default:
+                ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                    ASC_MEDIUM_NOT_PRESENT);
+                break;
             }
-            ide_atapi_cmd_ok(s);
         }
         break;
     case GPCMD_MECHANISM_STATUS: