Commit aea2a33c73f28ecd8f10b242ecadddcc79c1c28b

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent 2ea42952

Prevent CD-ROM media eject while device is locked

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

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 3 changed files with 27 additions and 10 deletions
... ... @@ -1566,11 +1566,15 @@ int bdrv_media_changed(BlockDriverState *bs)
1566 1566 /**
1567 1567 * If eject_flag is TRUE, eject the media. Otherwise, close the tray
1568 1568 */
1569   -void bdrv_eject(BlockDriverState *bs, int eject_flag)
  1569 +int bdrv_eject(BlockDriverState *bs, int eject_flag)
1570 1570 {
1571 1571 BlockDriver *drv = bs->drv;
1572 1572 int ret;
1573 1573  
  1574 + if (bs->locked) {
  1575 + return -EBUSY;
  1576 + }
  1577 +
1574 1578 if (!drv || !drv->bdrv_eject) {
1575 1579 ret = -ENOTSUP;
1576 1580 } else {
... ... @@ -1579,7 +1583,10 @@ void bdrv_eject(BlockDriverState *bs, int eject_flag)
1579 1583 if (ret == -ENOTSUP) {
1580 1584 if (eject_flag)
1581 1585 bdrv_close(bs);
  1586 + ret = 0;
1582 1587 }
  1588 +
  1589 + return ret;
1583 1590 }
1584 1591  
1585 1592 int bdrv_is_locked(BlockDriverState *bs)
... ...
... ... @@ -124,7 +124,7 @@ int bdrv_is_inserted(BlockDriverState *bs);
124 124 int bdrv_media_changed(BlockDriverState *bs);
125 125 int bdrv_is_locked(BlockDriverState *bs);
126 126 void bdrv_set_locked(BlockDriverState *bs, int locked);
127   -void bdrv_eject(BlockDriverState *bs, int eject_flag);
  127 +int bdrv_eject(BlockDriverState *bs, int eject_flag);
128 128 void bdrv_set_change_cb(BlockDriverState *bs,
129 129 void (*change_cb)(void *opaque), void *opaque);
130 130 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
... ...
hw/ide.c
... ... @@ -359,6 +359,7 @@
359 359 #define ASC_INCOMPATIBLE_FORMAT 0x30
360 360 #define ASC_MEDIUM_NOT_PRESENT 0x3a
361 361 #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
  362 +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53
362 363  
363 364 #define CFA_NO_ERROR 0x00
364 365 #define CFA_MISC_ERROR 0x09
... ... @@ -1822,18 +1823,27 @@ static void ide_atapi_cmd(IDEState *s)
1822 1823 break;
1823 1824 case GPCMD_START_STOP_UNIT:
1824 1825 {
1825   - int start, eject;
  1826 + int start, eject, err = 0;
1826 1827 start = packet[4] & 1;
1827 1828 eject = (packet[4] >> 1) & 1;
1828 1829  
1829   - if (eject && !start) {
1830   - /* eject the disk */
1831   - bdrv_eject(s->bs, 1);
1832   - } else if (eject && start) {
1833   - /* close the tray */
1834   - bdrv_eject(s->bs, 0);
  1830 + if (eject) {
  1831 + err = bdrv_eject(s->bs, !start);
  1832 + }
  1833 +
  1834 + switch (err) {
  1835 + case 0:
  1836 + ide_atapi_cmd_ok(s);
  1837 + break;
  1838 + case -EBUSY:
  1839 + ide_atapi_cmd_error(s, SENSE_NOT_READY,
  1840 + ASC_MEDIA_REMOVAL_PREVENTED);
  1841 + break;
  1842 + default:
  1843 + ide_atapi_cmd_error(s, SENSE_NOT_READY,
  1844 + ASC_MEDIUM_NOT_PRESENT);
  1845 + break;
1835 1846 }
1836   - ide_atapi_cmd_ok(s);
1837 1847 }
1838 1848 break;
1839 1849 case GPCMD_MECHANISM_STATUS:
... ...