block: Fix virtual media change for if=none

BlockDriverState member removable controls whether virtual media
change (monitor commands change, eject) is allowed.  It is set when
the "type hint" is BDRV_TYPE_CDROM or BDRV_TYPE_FLOPPY.

The type hint is only set by drive_init().  It sets BDRV_TYPE_FLOPPY
for if=floppy.  It sets BDRV_TYPE_CDROM for media=cdrom and if=ide,
scsi, xen, or none.

if=ide and if=scsi work, because the type hint makes it a CD-ROM.
if=xen likewise, I think.

For the same reason, if=none works when it's used by ide-drive or
scsi-disk.  For other guest devices, there are problems:

* fdc: you can't change virtual media

    $ qemu [...] -drive if=none,id=foo,... -global isa-fdc.driveA=foo
    QEMU 0.12.50 monitor - type 'help' for more information
    (qemu) eject foo
    Device 'foo' is not removable

  unless you add media=cdrom, but that makes it readonly.

* virtio: if you add media=cdrom, you can change virtual media.  If
  you eject, the guest gets I/O errors.  If you change, the guest sees
  the drive's contents suddenly change.

* scsi-generic: if you add media=cdrom, you can change virtual media.
  I didn't test what that does to the guest or the physical device,
  but it can't be pretty.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Markus Armbruster 2010-06-25 13:42:14 +02:00 committed by Kevin Wolf
parent 3ac906f771
commit 7d0d69509a
7 changed files with 24 additions and 3 deletions

View File

@ -1299,6 +1299,14 @@ BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read)
return is_read ? bs->on_read_error : bs->on_write_error; return is_read ? bs->on_read_error : bs->on_write_error;
} }
void bdrv_set_removable(BlockDriverState *bs, int removable)
{
bs->removable = removable;
if (removable && bs == bs_snapshots) {
bs_snapshots = NULL;
}
}
int bdrv_is_removable(BlockDriverState *bs) int bdrv_is_removable(BlockDriverState *bs)
{ {
return bs->removable; return bs->removable;

View File

@ -162,6 +162,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
BlockErrorAction on_write_error); BlockErrorAction on_write_error);
BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read); BlockErrorAction bdrv_get_on_error(BlockDriverState *bs, int is_read);
void bdrv_set_removable(BlockDriverState *bs, int removable);
int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_removable(BlockDriverState *bs);
int bdrv_is_read_only(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs); int bdrv_is_sg(BlockDriverState *bs);

View File

@ -1847,10 +1847,16 @@ static void fdctrl_result_timer(void *opaque)
static void fdctrl_connect_drives(FDCtrl *fdctrl) static void fdctrl_connect_drives(FDCtrl *fdctrl)
{ {
unsigned int i; unsigned int i;
FDrive *drive;
for (i = 0; i < MAX_FD; i++) { for (i = 0; i < MAX_FD; i++) {
fd_init(&fdctrl->drives[i]); drive = &fdctrl->drives[i];
fd_revalidate(&fdctrl->drives[i]);
fd_init(drive);
fd_revalidate(drive);
if (drive->bs) {
bdrv_set_removable(drive->bs, 1);
}
} }
} }

View File

@ -2629,6 +2629,7 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs,
pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
} }
ide_reset(s); ide_reset(s);
bdrv_set_removable(bs, s->is_cdrom);
} }
static void ide_init1(IDEBus *bus, int unit) static void ide_init1(IDEBus *bus, int unit)

View File

@ -1049,6 +1049,7 @@ static void scsi_destroy(SCSIDevice *dev)
static int scsi_disk_initfn(SCSIDevice *dev) static int scsi_disk_initfn(SCSIDevice *dev)
{ {
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
int is_cd;
DriveInfo *dinfo; DriveInfo *dinfo;
if (!s->qdev.conf.bs) { if (!s->qdev.conf.bs) {
@ -1056,6 +1057,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
return -1; return -1;
} }
s->bs = s->qdev.conf.bs; s->bs = s->qdev.conf.bs;
is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM;
if (!s->serial) { if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */ /* try to fall back to value set with legacy -drive serial=... */
@ -1072,7 +1074,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
return -1; return -1;
} }
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { if (is_cd) {
s->qdev.blocksize = 2048; s->qdev.blocksize = 2048;
} else { } else {
s->qdev.blocksize = s->qdev.conf.logical_block_size; s->qdev.blocksize = s->qdev.conf.logical_block_size;
@ -1081,6 +1083,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
s->qdev.type = TYPE_DISK; s->qdev.type = TYPE_DISK;
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
bdrv_set_removable(s->bs, is_cd);
return 0; return 0;
} }

View File

@ -509,6 +509,7 @@ static int scsi_generic_initfn(SCSIDevice *dev)
DPRINTF("block size %d\n", s->qdev.blocksize); DPRINTF("block size %d\n", s->qdev.blocksize);
s->driver_status = 0; s->driver_status = 0;
memset(s->sensebuf, 0, sizeof(s->sensebuf)); memset(s->sensebuf, 0, sizeof(s->sensebuf));
bdrv_set_removable(s->bs, 0);
return 0; return 0;
} }

View File

@ -500,6 +500,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
register_savevm("virtio-blk", virtio_blk_id++, 2, register_savevm("virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s); virtio_blk_save, virtio_blk_load, s);
bdrv_set_removable(s->bs, 0);
return &s->vdev; return &s->vdev;
} }