Skip to content

Commit

Permalink
block: Fix virtual media change for if=none
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Kevin Wolf <[email protected]>
  • Loading branch information
Markus Armbruster authored and kevmw committed Jul 2, 2010
1 parent 3ac906f commit 7d0d695
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 3 deletions.
8 changes: 8 additions & 0 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

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)
{
return bs->removable;
Expand Down
1 change: 1 addition & 0 deletions block.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ int bdrv_get_translation_hint(BlockDriverState *bs);
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
BlockErrorAction on_write_error);
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_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs);
Expand Down
10 changes: 8 additions & 2 deletions hw/fdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1847,10 +1847,16 @@ static void fdctrl_result_timer(void *opaque)
static void fdctrl_connect_drives(FDCtrl *fdctrl)
{
unsigned int i;
FDrive *drive;

for (i = 0; i < MAX_FD; i++) {
fd_init(&fdctrl->drives[i]);
fd_revalidate(&fdctrl->drives[i]);
drive = &fdctrl->drives[i];

fd_init(drive);
fd_revalidate(drive);
if (drive->bs) {
bdrv_set_removable(drive->bs, 1);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions hw/ide/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2629,6 +2629,7 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs,
pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
}
ide_reset(s);
bdrv_set_removable(bs, s->is_cdrom);
}

static void ide_init1(IDEBus *bus, int unit)
Expand Down
5 changes: 4 additions & 1 deletion hw/scsi-disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1049,13 +1049,15 @@ static void scsi_destroy(SCSIDevice *dev)
static int scsi_disk_initfn(SCSIDevice *dev)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
int is_cd;
DriveInfo *dinfo;

if (!s->qdev.conf.bs) {
error_report("scsi-disk: drive property not set");
return -1;
}
s->bs = s->qdev.conf.bs;
is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM;

if (!s->serial) {
/* try to fall back to value set with legacy -drive serial=... */
Expand All @@ -1072,7 +1074,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
return -1;
}

if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
if (is_cd) {
s->qdev.blocksize = 2048;
} else {
s->qdev.blocksize = s->qdev.conf.logical_block_size;
Expand All @@ -1081,6 +1083,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)

s->qdev.type = TYPE_DISK;
qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
bdrv_set_removable(s->bs, is_cd);
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions hw/scsi-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ static int scsi_generic_initfn(SCSIDevice *dev)
DPRINTF("block size %d\n", s->qdev.blocksize);
s->driver_status = 0;
memset(s->sensebuf, 0, sizeof(s->sensebuf));
bdrv_set_removable(s->bs, 0);
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions hw/virtio-blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
register_savevm("virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_removable(s->bs, 0);

return &s->vdev;
}

0 comments on commit 7d0d695

Please sign in to comment.