From 9dfd7c7a00dd700de36ca58005a7cb3934a62efb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 22 Jul 2009 16:43:04 +0200 Subject: [PATCH] switch -drive to QemuOpts. Demo QemuOpts in action ;) Implementing a alternative way to specify the filename should be just a few lines of code now once we decided how the cmd line syntax should look like. Signed-off-by: Gerd Hoffmann Signed-off-by: Anthony Liguori --- hw/device-hotplug.c | 12 +- sysemu.h | 14 +- vl.c | 308 ++++++++++++++++++++++++-------------------- 3 files changed, 178 insertions(+), 156 deletions(-) diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 8f0dec8b09..fd4cc3fb54 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -28,19 +28,19 @@ #include "block_int.h" #include "sysemu.h" -DriveInfo *add_init_drive(const char *opts) +DriveInfo *add_init_drive(const char *optstr) { int fatal_error; DriveInfo *dinfo; - DriveOpt *dopt; + QemuOpts *opts; - dopt = drive_add(NULL, "%s", opts); - if (!dopt) + opts = drive_add(NULL, "%s", optstr); + if (!opts) return NULL; - dinfo = drive_init(dopt, 0, current_machine, &fatal_error); + dinfo = drive_init(opts, current_machine, &fatal_error); if (!dinfo) { - drive_remove(dopt); + qemu_opts_del(opts); return NULL; } diff --git a/sysemu.h b/sysemu.h index 3748af1905..97d1581fd4 100644 --- a/sysemu.h +++ b/sysemu.h @@ -160,12 +160,6 @@ typedef enum { #define BLOCK_SERIAL_STRLEN 20 -typedef struct DriveOpt { - const char *file; - char opt[1024]; - TAILQ_ENTRY(DriveOpt) next; -} DriveOpt; - typedef struct DriveInfo { BlockDriverState *bdrv; char *id; @@ -173,7 +167,7 @@ typedef struct DriveInfo { BlockInterfaceType type; int bus; int unit; - DriveOpt *opt; + QemuOpts *opts; BlockInterfaceErrorAction onerror; char serial[BLOCK_SERIAL_STRLEN + 1]; TAILQ_ENTRY(DriveInfo) next; @@ -190,15 +184,13 @@ extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); extern DriveInfo *drive_get_by_id(char *id); extern int drive_get_max_bus(BlockInterfaceType type); extern void drive_uninit(BlockDriverState *bdrv); -extern void drive_remove(DriveOpt *opt); extern const char *drive_get_serial(BlockDriverState *bdrv); extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv); BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type); -extern DriveOpt *drive_add(const char *file, const char *fmt, ...); -extern DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *machine, - int *fatal_error); +extern QemuOpts *drive_add(const char *file, const char *fmt, ...); +extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error); /* acpi */ typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state); diff --git a/vl.c b/vl.c index 591186806b..2cff5a936c 100644 --- a/vl.c +++ b/vl.c @@ -1800,27 +1800,94 @@ static int bt_parse(const char *opt) #define MTD_ALIAS "if=mtd" #define SD_ALIAS "index=0,if=sd" -DriveOpt *drive_add(const char *file, const char *fmt, ...) +static QemuOptsList drive_opt_list = { + .name = "drive", + .head = TAILQ_HEAD_INITIALIZER(drive_opt_list.head), + .desc = { + { + .name = "bus", + .type = QEMU_OPT_NUMBER, + .help = "bus number", + },{ + .name = "unit", + .type = QEMU_OPT_NUMBER, + .help = "unit number (i.e. lun for scsi)", + },{ + .name = "if", + .type = QEMU_OPT_STRING, + .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", + },{ + .name = "index", + .type = QEMU_OPT_NUMBER, + },{ + .name = "cyls", + .type = QEMU_OPT_NUMBER, + .help = "number of cylinders (ide disk geometry)", + },{ + .name = "heads", + .type = QEMU_OPT_NUMBER, + .help = "number of heads (ide disk geometry)", + },{ + .name = "secs", + .type = QEMU_OPT_NUMBER, + .help = "number of sectors (ide disk geometry)", + },{ + .name = "trans", + .type = QEMU_OPT_STRING, + .help = "chs translation (auto, lba. none)", + },{ + .name = "media", + .type = QEMU_OPT_STRING, + .help = "media type (disk, cdrom)", + },{ + .name = "snapshot", + .type = QEMU_OPT_BOOL, + },{ + .name = "file", + .type = QEMU_OPT_STRING, + .help = "disk image", + },{ + .name = "cache", + .type = QEMU_OPT_STRING, + .help = "host cache usage (none, writeback, writethrough)", + },{ + .name = "format", + .type = QEMU_OPT_STRING, + .help = "disk format (raw, qcow2, ...)", + },{ + .name = "serial", + .type = QEMU_OPT_STRING, + },{ + .name = "werror", + .type = QEMU_OPT_STRING, + },{ + .name = "addr", + .type = QEMU_OPT_STRING, + .help = "pci address (virtio only)", + }, + { /* end if list */ } + }, +}; + +QemuOpts *drive_add(const char *file, const char *fmt, ...) { va_list ap; - DriveOpt *dopt; + char optstr[1024]; + QemuOpts *opts; - dopt = qemu_mallocz(sizeof(*dopt)); - - dopt->file = file; va_start(ap, fmt); - vsnprintf(dopt->opt, - sizeof(dopt->opt), fmt, ap); + vsnprintf(optstr, sizeof(optstr), fmt, ap); va_end(ap); - TAILQ_INSERT_TAIL(&driveopts, dopt, next); - return dopt; -} - -void drive_remove(DriveOpt *dopt) -{ - TAILQ_REMOVE(&driveopts, dopt, next); - qemu_free(dopt); + opts = qemu_opts_parse(&drive_opt_list, optstr, NULL); + if (!opts) { + fprintf(stderr, "%s: huh? duplicate? (%s)\n", + __FUNCTION__, optstr); + return NULL; + } + if (file) + qemu_opt_set(opts, "file", file); + return opts; } DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) @@ -1901,20 +1968,20 @@ void drive_uninit(BlockDriverState *bdrv) TAILQ_FOREACH(dinfo, &drives, next) { if (dinfo->bdrv != bdrv) continue; - drive_remove(dinfo->opt); + qemu_opts_del(dinfo->opts); TAILQ_REMOVE(&drives, dinfo, next); qemu_free(dinfo); break; } } -DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, +DriveInfo *drive_init(QemuOpts *opts, void *opaque, int *fatal_error) { - char buf[128]; - char file[1024]; + const char *buf; + const char *file = NULL; char devname[128]; - char serial[21]; + const char *serial; const char *mediastr = ""; BlockInterfaceType type; enum { MEDIA_DISK, MEDIA_CDROM } media; @@ -1928,27 +1995,11 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, int bdrv_flags, onerror; const char *devaddr; DriveInfo *dinfo; - char *str = arg->opt; - static const char * const params[] = { "bus", "unit", "if", "index", - "cyls", "heads", "secs", "trans", - "media", "snapshot", "file", - "cache", "format", "serial", - "werror", "addr", "id", - NULL }; + int snapshot = 0; + *fatal_error = 1; - if (check_params(buf, sizeof(buf), params, str) < 0) { - fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n", - buf, str); - return NULL; - } - - file[0] = 0; - cyls = heads = secs = 0; - bus_id = 0; - unit_id = -1; translation = BIOS_ATA_TRANSLATION_AUTO; - index = -1; cache = 1; if (machine->use_scsi) { @@ -1963,24 +2014,20 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, 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); - if (get_param_value(buf, sizeof(buf), "bus", str)) { - bus_id = strtol(buf, NULL, 0); - if (bus_id < 0) { - fprintf(stderr, "qemu: '%s' invalid bus id\n", str); - return NULL; - } - } + cyls = qemu_opt_get_number(opts, "cyls", 0); + heads = qemu_opt_get_number(opts, "heads", 0); + secs = qemu_opt_get_number(opts, "secs", 0); - if (get_param_value(buf, sizeof(buf), "unit", str)) { - unit_id = strtol(buf, NULL, 0); - if (unit_id < 0) { - fprintf(stderr, "qemu: '%s' invalid unit id\n", str); - return NULL; - } - } + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); - if (get_param_value(buf, sizeof(buf), "if", str)) { + 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; @@ -2007,51 +2054,31 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, type = IF_XEN; max_devs = 0; } else { - fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf); + fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); return NULL; } } - if (get_param_value(buf, sizeof(buf), "index", str)) { - index = strtol(buf, NULL, 0); - if (index < 0) { - fprintf(stderr, "qemu: '%s' invalid index\n", str); - return NULL; - } - } - - if (get_param_value(buf, sizeof(buf), "cyls", str)) { - cyls = strtol(buf, NULL, 0); - } - - if (get_param_value(buf, sizeof(buf), "heads", str)) { - heads = strtol(buf, NULL, 0); - } - - if (get_param_value(buf, sizeof(buf), "secs", str)) { - secs = strtol(buf, NULL, 0); - } - if (cyls || heads || secs) { if (cyls < 1 || cyls > 16383) { - fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str); + fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); return NULL; } if (heads < 1 || heads > 16) { - fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str); + fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); return NULL; } if (secs < 1 || secs > 63) { - fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str); + fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); return NULL; } } - if (get_param_value(buf, sizeof(buf), "trans", str)) { + if ((buf = qemu_opt_get(opts, "trans")) != NULL) { if (!cyls) { fprintf(stderr, "qemu: '%s' trans must be used with cyls,heads and secs\n", - str); + buf); return NULL; } if (!strcmp(buf, "none")) @@ -2061,39 +2088,28 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, else if (!strcmp(buf, "auto")) translation = BIOS_ATA_TRANSLATION_AUTO; else { - fprintf(stderr, "qemu: '%s' invalid translation type\n", str); + fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); return NULL; } } - if (get_param_value(buf, sizeof(buf), "media", str)) { + 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", str); + "qemu: '%s' invalid physical CHS format\n", buf); return NULL; } media = MEDIA_CDROM; } else { - fprintf(stderr, "qemu: '%s' invalid media\n", str); + fprintf(stderr, "qemu: '%s' invalid media\n", buf); return NULL; } } - if (get_param_value(buf, sizeof(buf), "snapshot", str)) { - if (!strcmp(buf, "on")) - snapshot = 1; - else if (!strcmp(buf, "off")) - snapshot = 0; - else { - fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str); - return NULL; - } - } - - if (get_param_value(buf, sizeof(buf), "cache", str)) { + if ((buf = qemu_opt_get(opts, "cache")) != NULL) { if (!strcmp(buf, "off") || !strcmp(buf, "none")) cache = 0; else if (!strcmp(buf, "writethrough")) @@ -2106,7 +2122,7 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, } } - if (get_param_value(buf, sizeof(buf), "format", str)) { + if ((buf = qemu_opt_get(opts, "format")) != NULL) { if (strcmp(buf, "?") == 0) { fprintf(stderr, "qemu: Supported formats:"); bdrv_iterate_format(bdrv_format_print, NULL); @@ -2120,16 +2136,8 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, } } - if (arg->file == NULL) - get_param_value(file, sizeof(file), "file", str); - else - pstrcpy(file, sizeof(file), arg->file); - - if (!get_param_value(serial, sizeof(serial), "serial", str)) - memset(serial, 0, sizeof(serial)); - onerror = BLOCK_ERR_STOP_ENOSPC; - if (get_param_value(buf, sizeof(serial), "werror", str)) { + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) { fprintf(stderr, "werror is no supported by this format\n"); return NULL; @@ -2148,13 +2156,11 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, } } - devaddr = NULL; - if (get_param_value(buf, sizeof(buf), "addr", str)) { + if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { if (type != IF_VIRTIO) { - fprintf(stderr, "addr is not supported by in '%s'\n", str); + fprintf(stderr, "addr is not supported\n"); return NULL; } - devaddr = strdup(buf); } /* compute bus and unit according index */ @@ -2162,7 +2168,7 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, if (index != -1) { if (bus_id != 0 || unit_id != -1) { fprintf(stderr, - "qemu: '%s' index cannot be used with bus and unit\n", str); + "qemu: index cannot be used with bus and unit\n"); return NULL; } if (max_devs == 0) @@ -2193,8 +2199,8 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, /* check unit id */ if (max_devs && unit_id >= max_devs) { - fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n", - str, unit_id, max_devs - 1); + fprintf(stderr, "qemu: unit %d too big (max is %d)\n", + unit_id, max_devs - 1); return NULL; } @@ -2210,26 +2216,29 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, /* init */ dinfo = qemu_mallocz(sizeof(*dinfo)); - if (!get_param_value(buf, sizeof(buf), "id", str)) { + if ((buf = qemu_opt_get(opts, "id")) != 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(buf, sizeof(buf), "%s%i%s%i", + snprintf(dinfo->id, 32, "%s%i%s%i", devname, bus_id, mediastr, unit_id); else - snprintf(buf, sizeof(buf), "%s%s%i", + snprintf(dinfo->id, 32, "%s%s%i", devname, mediastr, unit_id); } - dinfo->id = qemu_strdup(buf); dinfo->bdrv = bdrv_new(dinfo->id); dinfo->devaddr = devaddr; dinfo->type = type; dinfo->bus = bus_id; dinfo->unit = unit_id; dinfo->onerror = onerror; - dinfo->opt = arg; - strncpy(dinfo->serial, serial, sizeof(serial)); + dinfo->opts = opts; + if (serial) + strncpy(dinfo->serial, serial, sizeof(serial)); TAILQ_INSERT_TAIL(&drives, dinfo, next); switch(type) { @@ -2261,7 +2270,7 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, case IF_COUNT: abort(); } - if (!file[0]) { + if (!file) { *fatal_error = 0; return NULL; } @@ -2285,6 +2294,26 @@ DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque, return dinfo; } +static int drive_init_func(QemuOpts *opts, void *opaque) +{ + QEMUMachine *machine = opaque; + int fatal_error = 0; + + if (drive_init(opts, machine, &fatal_error) == NULL) { + if (fatal_error) + return 1; + } + return 0; +} + +static int drive_enable_snapshot(QemuOpts *opts, void *opaque) +{ + if (NULL == qemu_opt_get(opts, "snapshot")) { + qemu_opt_set(opts, "snapshot", "on"); + } + return 0; +} + void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) { boot_set_handler = func; @@ -4815,7 +4844,7 @@ int main(int argc, char **argv, char **envp) int cyls, heads, secs, translation; const char *net_clients[MAX_NET_CLIENTS]; int nb_net_clients; - DriveOpt *dopt, *hda_opt = NULL; + QemuOpts *hda_opts = NULL; int optind; const char *r, *optarg; CharDriverState *monitor_hd = NULL; @@ -4923,7 +4952,7 @@ int main(int argc, char **argv, char **envp) break; r = argv[optind]; if (r[0] != '-') { - hda_opt = drive_add(argv[optind++], HD_ALIAS, 0); + hda_opts = drive_add(argv[optind++], HD_ALIAS, 0); } else { const QEMUOption *popt; @@ -4987,9 +5016,9 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_hda: if (cyls == 0) - hda_opt = drive_add(optarg, HD_ALIAS, 0); + hda_opts = drive_add(optarg, HD_ALIAS, 0); else - hda_opt = drive_add(optarg, HD_ALIAS + hda_opts = drive_add(optarg, HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s", 0, cyls, heads, secs, translation == BIOS_ATA_TRANSLATION_LBA ? @@ -5051,15 +5080,19 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid physical CHS format\n"); exit(1); } - if (hda_opt != NULL) - snprintf(hda_opt->opt, - sizeof(hda_opt->opt), - HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s", - 0, cyls, heads, secs, - translation == BIOS_ATA_TRANSLATION_LBA ? - ",trans=lba" : - translation == BIOS_ATA_TRANSLATION_NONE ? - ",trans=none" : ""); + if (hda_opts != NULL) { + char num[16]; + snprintf(num, sizeof(num), "%d", cyls); + qemu_opt_set(hda_opts, "cyls", num); + snprintf(num, sizeof(num), "%d", heads); + qemu_opt_set(hda_opts, "heads", num); + snprintf(num, sizeof(num), "%d", secs); + qemu_opt_set(hda_opts, "secs", num); + if (translation == BIOS_ATA_TRANSLATION_LBA) + qemu_opt_set(hda_opts, "trans", "lba"); + if (translation == BIOS_ATA_TRANSLATION_NONE) + qemu_opt_set(hda_opts, "trans", "none"); + } } break; case QEMU_OPTION_numa: @@ -5771,13 +5804,10 @@ int main(int argc, char **argv, char **envp) drive_add(NULL, SD_ALIAS); /* open the virtual block devices */ - - TAILQ_FOREACH(dopt, &driveopts, next) { - int fatal_error; - if (drive_init(dopt, snapshot, machine, &fatal_error) == NULL) - if (fatal_error) - exit(1); - } + if (snapshot) + qemu_opts_foreach(&drive_opt_list, drive_enable_snapshot, NULL, 0); + if (qemu_opts_foreach(&drive_opt_list, drive_init_func, machine, 1) != 0) + exit(1); register_savevm("timer", 0, 2, timer_save, timer_load, NULL); register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);