aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2010-06-25 13:42:14 +0200
committerKevin Wolf <kwolf@redhat.com>2010-07-02 13:18:02 +0200
commit7d0d69509a966a5328e4fed7d0a942112d431c35 (patch)
treee2d3a6cb0b5f07d8220f2361605ba689220560b1
parent3ac906f771c42363dc05e0a393defd21a57d3790 (diff)
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>
-rw-r--r--block.c8
-rw-r--r--block.h1
-rw-r--r--hw/fdc.c10
-rw-r--r--hw/ide/core.c1
-rw-r--r--hw/scsi-disk.c5
-rw-r--r--hw/scsi-generic.c1
-rw-r--r--hw/virtio-blk.c1
7 files changed, 24 insertions, 3 deletions
diff --git a/block.c b/block.c
index 003d13213e..9176decf33 100644
--- a/block.c
+++ b/block.c
@@ -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;
diff --git a/block.h b/block.h
index 012c2a1156..3d03b3e041 100644
--- a/block.h
+++ b/block.h
@@ -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);
diff --git a/hw/fdc.c b/hw/fdc.c
index 1496cfa14d..6c748782e3 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -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);
+ }
}
}
diff --git a/hw/ide/core.c b/hw/ide/core.c
index cc4591baa0..ebdceb5fec 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -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)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index e900eff024..3e41011ccb 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -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;
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 79347f4a67..3915e7844e 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -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;
}
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 71c5d21e61..f0b3ba5cb1 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -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;
}