2009-06-24 16:22:39 +00:00
|
|
|
From b9052762b5ae94ff7027f0fd0916b1c289bfffef Mon Sep 17 00:00:00 2001
|
2009-06-03 15:02:25 +00:00
|
|
|
From: Mark McLoughlin <markmc@redhat.com>
|
2009-06-24 16:22:39 +00:00
|
|
|
Date: Wed, 27 May 2009 10:06:11 +0100
|
|
|
|
Subject: [PATCH 5/7] Prevent CD-ROM media eject while device is locked
|
2009-06-03 15:02:25 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2009-06-24 16:22:39 +00:00
|
|
|
(cherry picked from commit aea2a33c73f28ecd8f10b242ecadddcc79c1c28b)
|
|
|
|
|
2009-06-03 15:02:25 +00:00
|
|
|
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
|
2009-06-24 16:22:39 +00:00
|
|
|
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
2009-06-03 15:02:25 +00:00
|
|
|
---
|
|
|
|
block.c | 9 ++++++++-
|
|
|
|
block.h | 2 +-
|
|
|
|
hw/ide.c | 26 ++++++++++++++++++--------
|
|
|
|
3 files changed, 27 insertions(+), 10 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/block.c b/block.c
|
2009-06-24 16:22:39 +00:00
|
|
|
index acb8976..b619147 100644
|
2009-06-03 15:02:25 +00:00
|
|
|
--- a/block.c
|
|
|
|
+++ b/block.c
|
2009-06-24 16:22:39 +00:00
|
|
|
@@ -1591,11 +1591,15 @@ int bdrv_media_changed(BlockDriverState *bs)
|
2009-06-03 15:02:25 +00:00
|
|
|
/**
|
|
|
|
* 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 {
|
2009-06-24 16:22:39 +00:00
|
|
|
@@ -1604,7 +1608,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
|
2009-06-03 15:02:25 +00:00
|
|
|
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
|
2009-06-24 16:22:39 +00:00
|
|
|
index 5aef076..a4789b2 100644
|
2009-06-03 15:02:25 +00:00
|
|
|
--- a/block.h
|
|
|
|
+++ b/block.h
|
|
|
|
@@ -136,7 +136,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);
|
|
|
|
diff --git a/hw/ide.c b/hw/ide.c
|
2009-06-24 16:22:39 +00:00
|
|
|
index b2a1288..2c918df 100644
|
2009-06-03 15:02:25 +00:00
|
|
|
--- a/hw/ide.c
|
|
|
|
+++ b/hw/ide.c
|
|
|
|
@@ -359,6 +359,7 @@
|
|
|
|
#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
|
2009-06-24 16:22:39 +00:00
|
|
|
@@ -1822,18 +1823,27 @@ static void ide_atapi_cmd(IDEState *s)
|
2009-06-03 15:02:25 +00:00
|
|
|
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:
|
|
|
|
--
|
|
|
|
1.6.2.2
|
|
|
|
|