diff options
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 499 |
1 files changed, 8 insertions, 491 deletions
@@ -137,7 +137,7 @@ int main(int argc, char **argv) #include "qemu-char.h" #include "cache-utils.h" #include "block.h" -#include "block_int.h" +#include "blockdev.h" #include "block-migration.h" #include "dma.h" #include "audio/audio.h" @@ -170,10 +170,6 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; -/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available - to store the VM snapshots */ -struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); -struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; DisplayType display_type = DT_DEFAULT; const char* keyboard_layout = NULL; @@ -633,492 +629,12 @@ static int bt_parse(const char *opt) #define MTD_ALIAS "if=mtd" #define SD_ALIAS "index=0,if=sd" -QemuOpts *drive_add(const char *file, const char *fmt, ...) -{ - va_list ap; - char optstr[1024]; - QemuOpts *opts; - - va_start(ap, fmt); - vsnprintf(optstr, sizeof(optstr), fmt, ap); - va_end(ap); - - opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0); - if (!opts) { - return NULL; - } - if (file) - qemu_opt_set(opts, "file", file); - return opts; -} - -DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) -{ - DriveInfo *dinfo; - - /* seek interface, bus and unit */ - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->type == type && - dinfo->bus == bus && - dinfo->unit == unit) - return dinfo; - } - - return NULL; -} - -DriveInfo *drive_get_by_id(const char *id) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (strcmp(id, dinfo->id)) - continue; - return dinfo; - } - return NULL; -} - -int drive_get_max_bus(BlockInterfaceType type) -{ - int max_bus; - DriveInfo *dinfo; - - max_bus = -1; - QTAILQ_FOREACH(dinfo, &drives, next) { - if(dinfo->type == type && - dinfo->bus > max_bus) - max_bus = dinfo->bus; - } - return max_bus; -} - -const char *drive_get_serial(BlockDriverState *bdrv) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bdrv) - return dinfo->serial; - } - - return "\0"; -} - -BlockInterfaceErrorAction drive_get_on_error( - BlockDriverState *bdrv, int is_read) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bdrv) - return is_read ? dinfo->on_read_error : dinfo->on_write_error; - } - - return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC; -} - -static void bdrv_format_print(void *opaque, const char *name) -{ - fprintf(stderr, " %s", name); -} - -void drive_uninit(DriveInfo *dinfo) -{ - qemu_opts_del(dinfo->opts); - bdrv_delete(dinfo->bdrv); - QTAILQ_REMOVE(&drives, dinfo, next); - qemu_free(dinfo); -} - -static int parse_block_error_action(const char *buf, int is_read) -{ - if (!strcmp(buf, "ignore")) { - return BLOCK_ERR_IGNORE; - } else if (!is_read && !strcmp(buf, "enospc")) { - return BLOCK_ERR_STOP_ENOSPC; - } else if (!strcmp(buf, "stop")) { - return BLOCK_ERR_STOP_ANY; - } else if (!strcmp(buf, "report")) { - return BLOCK_ERR_REPORT; - } else { - fprintf(stderr, "qemu: '%s' invalid %s error action\n", - buf, is_read ? "read" : "write"); - return -1; - } -} - -DriveInfo *drive_init(QemuOpts *opts, void *opaque, - int *fatal_error) -{ - const char *buf; - const char *file = NULL; - char devname[128]; - const char *serial; - const char *mediastr = ""; - BlockInterfaceType type; - enum { MEDIA_DISK, MEDIA_CDROM } media; - int bus_id, unit_id; - int cyls, heads, secs, translation; - BlockDriver *drv = NULL; - QEMUMachine *machine = opaque; - int max_devs; - int index; - int ro = 0; - int bdrv_flags = 0; - int on_read_error, on_write_error; - const char *devaddr; - DriveInfo *dinfo; - int snapshot = 0; - - *fatal_error = 1; - - translation = BIOS_ATA_TRANSLATION_AUTO; - - if (machine && machine->use_scsi) { - type = IF_SCSI; - max_devs = MAX_SCSI_DEVS; - pstrcpy(devname, sizeof(devname), "scsi"); - } else { - type = IF_IDE; - max_devs = MAX_IDE_DEVS; - pstrcpy(devname, sizeof(devname), "ide"); - } - media = MEDIA_DISK; - - /* extract parameters */ - bus_id = qemu_opt_get_number(opts, "bus", 0); - unit_id = qemu_opt_get_number(opts, "unit", -1); - index = qemu_opt_get_number(opts, "index", -1); - - cyls = qemu_opt_get_number(opts, "cyls", 0); - heads = qemu_opt_get_number(opts, "heads", 0); - secs = qemu_opt_get_number(opts, "secs", 0); - - snapshot = qemu_opt_get_bool(opts, "snapshot", 0); - ro = qemu_opt_get_bool(opts, "readonly", 0); - - file = qemu_opt_get(opts, "file"); - serial = qemu_opt_get(opts, "serial"); - - if ((buf = qemu_opt_get(opts, "if")) != NULL) { - pstrcpy(devname, sizeof(devname), buf); - if (!strcmp(buf, "ide")) { - type = IF_IDE; - max_devs = MAX_IDE_DEVS; - } else if (!strcmp(buf, "scsi")) { - type = IF_SCSI; - max_devs = MAX_SCSI_DEVS; - } else if (!strcmp(buf, "floppy")) { - type = IF_FLOPPY; - max_devs = 0; - } else if (!strcmp(buf, "pflash")) { - type = IF_PFLASH; - max_devs = 0; - } else if (!strcmp(buf, "mtd")) { - type = IF_MTD; - max_devs = 0; - } else if (!strcmp(buf, "sd")) { - type = IF_SD; - max_devs = 0; - } else if (!strcmp(buf, "virtio")) { - type = IF_VIRTIO; - max_devs = 0; - } else if (!strcmp(buf, "xen")) { - type = IF_XEN; - max_devs = 0; - } else if (!strcmp(buf, "none")) { - type = IF_NONE; - max_devs = 0; - } else { - fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); - return NULL; - } - } - - if (cyls || heads || secs) { - if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { - fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); - return NULL; - } - if (heads < 1 || (type == IF_IDE && heads > 16)) { - fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); - return NULL; - } - if (secs < 1 || (type == IF_IDE && secs > 63)) { - fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "trans")) != NULL) { - if (!cyls) { - fprintf(stderr, - "qemu: '%s' trans must be used with cyls,heads and secs\n", - buf); - return NULL; - } - if (!strcmp(buf, "none")) - translation = BIOS_ATA_TRANSLATION_NONE; - else if (!strcmp(buf, "lba")) - translation = BIOS_ATA_TRANSLATION_LBA; - else if (!strcmp(buf, "auto")) - translation = BIOS_ATA_TRANSLATION_AUTO; - else { - fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "media")) != NULL) { - if (!strcmp(buf, "disk")) { - media = MEDIA_DISK; - } else if (!strcmp(buf, "cdrom")) { - if (cyls || secs || heads) { - fprintf(stderr, - "qemu: '%s' invalid physical CHS format\n", buf); - return NULL; - } - media = MEDIA_CDROM; - } else { - fprintf(stderr, "qemu: '%s' invalid media\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "cache")) != NULL) { - if (!strcmp(buf, "off") || !strcmp(buf, "none")) { - bdrv_flags |= BDRV_O_NOCACHE; - } else if (!strcmp(buf, "writeback")) { - bdrv_flags |= BDRV_O_CACHE_WB; - } else if (!strcmp(buf, "unsafe")) { - bdrv_flags |= BDRV_O_CACHE_WB; - bdrv_flags |= BDRV_O_NO_FLUSH; - } else if (!strcmp(buf, "writethrough")) { - /* this is the default */ - } else { - fprintf(stderr, "qemu: invalid cache option\n"); - return NULL; - } - } - -#ifdef CONFIG_LINUX_AIO - if ((buf = qemu_opt_get(opts, "aio")) != NULL) { - if (!strcmp(buf, "native")) { - bdrv_flags |= BDRV_O_NATIVE_AIO; - } else if (!strcmp(buf, "threads")) { - /* this is the default */ - } else { - fprintf(stderr, "qemu: invalid aio option\n"); - return NULL; - } - } -#endif - - if ((buf = qemu_opt_get(opts, "format")) != NULL) { - if (strcmp(buf, "?") == 0) { - fprintf(stderr, "qemu: Supported formats:"); - bdrv_iterate_format(bdrv_format_print, NULL); - fprintf(stderr, "\n"); - return NULL; - } - drv = bdrv_find_whitelisted_format(buf); - if (!drv) { - fprintf(stderr, "qemu: '%s' invalid format\n", buf); - return NULL; - } - } - - on_write_error = BLOCK_ERR_STOP_ENOSPC; - if ((buf = qemu_opt_get(opts, "werror")) != NULL) { - if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "werror is no supported by this format\n"); - return NULL; - } - - on_write_error = parse_block_error_action(buf, 0); - if (on_write_error < 0) { - return NULL; - } - } - - on_read_error = BLOCK_ERR_REPORT; - if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { - if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "rerror is no supported by this format\n"); - return NULL; - } - - on_read_error = parse_block_error_action(buf, 1); - if (on_read_error < 0) { - return NULL; - } - } - - if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { - if (type != IF_VIRTIO) { - fprintf(stderr, "addr is not supported\n"); - return NULL; - } - } - - /* compute bus and unit according index */ - - if (index != -1) { - if (bus_id != 0 || unit_id != -1) { - fprintf(stderr, - "qemu: index cannot be used with bus and unit\n"); - return NULL; - } - if (max_devs == 0) - { - unit_id = index; - bus_id = 0; - } else { - unit_id = index % max_devs; - bus_id = index / max_devs; - } - } - - /* if user doesn't specify a unit_id, - * try to find the first free - */ - - if (unit_id == -1) { - unit_id = 0; - while (drive_get(type, bus_id, unit_id) != NULL) { - unit_id++; - if (max_devs && unit_id >= max_devs) { - unit_id -= max_devs; - bus_id++; - } - } - } - - /* check unit id */ - - if (max_devs && unit_id >= max_devs) { - fprintf(stderr, "qemu: unit %d too big (max is %d)\n", - unit_id, max_devs - 1); - return NULL; - } - - /* - * ignore multiple definitions - */ - - if (drive_get(type, bus_id, unit_id) != NULL) { - *fatal_error = 0; - return NULL; - } - - /* init */ - - dinfo = qemu_mallocz(sizeof(*dinfo)); - if ((buf = qemu_opts_id(opts)) != NULL) { - dinfo->id = qemu_strdup(buf); - } else { - /* no id supplied -> create one */ - dinfo->id = qemu_mallocz(32); - if (type == IF_IDE || type == IF_SCSI) - mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; - if (max_devs) - snprintf(dinfo->id, 32, "%s%i%s%i", - devname, bus_id, mediastr, unit_id); - else - snprintf(dinfo->id, 32, "%s%s%i", - devname, mediastr, unit_id); - } - dinfo->bdrv = bdrv_new(dinfo->id); - dinfo->devaddr = devaddr; - dinfo->type = type; - dinfo->bus = bus_id; - dinfo->unit = unit_id; - dinfo->on_read_error = on_read_error; - dinfo->on_write_error = on_write_error; - dinfo->opts = opts; - if (serial) - strncpy(dinfo->serial, serial, sizeof(serial)); - QTAILQ_INSERT_TAIL(&drives, dinfo, next); - - switch(type) { - case IF_IDE: - case IF_SCSI: - case IF_XEN: - case IF_NONE: - switch(media) { - case MEDIA_DISK: - if (cyls != 0) { - bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); - bdrv_set_translation_hint(dinfo->bdrv, translation); - } - break; - case MEDIA_CDROM: - bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); - break; - } - break; - case IF_SD: - /* FIXME: This isn't really a floppy, but it's a reasonable - approximation. */ - case IF_FLOPPY: - bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); - break; - case IF_PFLASH: - case IF_MTD: - break; - case IF_VIRTIO: - /* add virtio block device */ - opts = qemu_opts_create(&qemu_device_opts, NULL, 0); - qemu_opt_set(opts, "driver", "virtio-blk-pci"); - qemu_opt_set(opts, "drive", dinfo->id); - if (devaddr) - qemu_opt_set(opts, "addr", devaddr); - break; - case IF_COUNT: - abort(); - } - if (!file) { - *fatal_error = 0; - return NULL; - } - if (snapshot) { - /* always use cache=unsafe with snapshot */ - bdrv_flags &= ~BDRV_O_CACHE_MASK; - bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); - } - - if (media == MEDIA_CDROM) { - /* CDROM is fine for any interface, don't check. */ - ro = 1; - } else if (ro == 1) { - if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) { - fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n"); - return NULL; - } - } - - bdrv_flags |= ro ? 0 : BDRV_O_RDWR; - - if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) { - fprintf(stderr, "qemu: could not open disk image %s: %s\n", - file, strerror(errno)); - return NULL; - } - - if (bdrv_key_required(dinfo->bdrv)) - autostart = 0; - *fatal_error = 0; - return dinfo; -} - static int drive_init_func(QemuOpts *opts, void *opaque) { - QEMUMachine *machine = opaque; + int *use_scsi = opaque; int fatal_error = 0; - if (drive_init(opts, machine, &fatal_error) == NULL) { + if (drive_init(opts, *use_scsi, &fatal_error) == NULL) { if (fatal_error) return 1; } @@ -1297,7 +813,7 @@ static void smp_parse(const char *optarg) /***********************************************************/ /* USB devices */ -static int usb_device_add(const char *devname, int is_hotplug) +static int usb_device_add(const char *devname) { const char *p; USBDevice *dev = NULL; @@ -1349,7 +865,7 @@ static int usb_device_del(const char *devname) static int usb_parse(const char *cmdline) { int r; - r = usb_device_add(cmdline, 0); + r = usb_device_add(cmdline); if (r < 0) { fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline); } @@ -1359,7 +875,7 @@ static int usb_parse(const char *cmdline) void do_usb_add(Monitor *mon, const QDict *qdict) { const char *devname = qdict_get_str(qdict, "devname"); - if (usb_device_add(devname, 1) < 0) { + if (usb_device_add(devname) < 0) { error_report("could not add USB device '%s'", devname); } } @@ -1841,6 +1357,7 @@ static void main_loop(void) vm_stop(r); } } + bdrv_close_all(); pause_all_vcpus(); } @@ -3243,7 +2760,7 @@ int main(int argc, char **argv, char **envp) /* open the virtual block devices */ if (snapshot) qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0); - if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0) + if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0) exit(1); register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, |