Commit 7d0d6950 authored by Markus Armbruster's avatar Markus Armbruster Committed by Kevin Wolf
Browse files

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: default avatarMarkus Armbruster <armbru@redhat.com>
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent 3ac906f7
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
+8 −2
Original line number Diff line number Diff line
@@ -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);
        }
    }
}

+1 −0
Original line number Diff line number Diff line
@@ -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)
+4 −1
Original line number Diff line number Diff line
@@ -1049,6 +1049,7 @@ 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) {
@@ -1056,6 +1057,7 @@ static int scsi_disk_initfn(SCSIDevice *dev)
        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=... */
@@ -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;
@@ -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;
}

Loading