|
Mark McLoughlin |
e37615 |
From: Mark McLoughlin <markmc@redhat.com>
|
|
Mark McLoughlin |
e37615 |
Subject: [PATCH] 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 |
e37615 |
Signed-off-by: Mark McLoughlin <markmc@redhat.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 |
e37615 |
index 9a2873f..863897a 100644
|
|
Mark McLoughlin |
e37615 |
--- a/block.c
|
|
Mark McLoughlin |
e37615 |
+++ b/block.c
|
|
Mark McLoughlin |
e37615 |
@@ -1591,11 +11591,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 |
e37615 |
@@ -1604,7 +1604,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 |
e37615 |
index 979781a..e1070e9 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 |
e37615 |
index 6ad1d08..9b93e7f 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 |
e37615 |
@@ -1822,18 +1822,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 |
|