From: Paul Durrant Date: Thu, 26 Apr 2018 14:54:29 +0000 (+0100) Subject: stuff X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=883dc9ca9e3bc9ec0329eeae0978613b20f82d4c;p=people%2Fpauldu%2Fqemu.git stuff Signed-off-by: Paul Durrant --- diff --git a/hw/block/xen_qdisk.c b/hw/block/xen_qdisk.c index 08dab165ec..c18ad8e1a8 100644 --- a/hw/block/xen_qdisk.c +++ b/hw/block/xen_qdisk.c @@ -10,12 +10,20 @@ #include "xen_blkif.h" #include "trace.h" -typedef enum XenVdevType { - XEN_VDEV_TYPE_XVD, - XEN_VDEV_TYPE_HD, - XEN_VDEV_TYPE_SD, - XEN_VDEV_TYPE__MAX -} XenVdevType; +typedef enum XenQdiskVdevType { + XEN_QDISK_VDEV_TYPE_DP, + XEN_QDISK_VDEV_TYPE_XVD, + XEN_QDISK_VDEV_TYPE_HD, + XEN_QDISK_VDEV_TYPE_SD, + XEN_QDISK_VDEV_TYPE__MAX +} XenQdiskVdevType; + +typedef struct XenQdiskVdev { + XenQdiskVdevType type; + unsigned int disk; + unsigned int partition; + bool valid; +} XenQdiskVdev; #define TYPE_XEN_QDISK_BACKEND "xen-qdisk" #define XEN_QDISK_BACKEND(obj) \ @@ -40,10 +48,8 @@ struct ioreq { struct XenQdiskBackend { XenBackend xendev; - XenVdevType type; - int disk; - unsigned int partition; BlockConf conf; + XenQdiskVdev vdev; bool discard_enable; unsigned int max_ring_page_order; BlockBackend *blk; @@ -559,45 +565,43 @@ static void blk_handle_requests(XenQdiskBackend *d) static char *xen_qdisk_get_name(XenBackend *dev, Error **errp) { XenQdiskBackend *d = XEN_QDISK_BACKEND(dev); + XenQdiskVdev *vdev = &d->vdev; unsigned int number; - if (d->disk < 0) { - error_setg(errp, "invalid disk number (%d)", d->disk); - return NULL; - } - - switch (d->type) { - case XEN_VDEV_TYPE_XVD: - if (d->disk < (1 << 4) && d->partition < (1 << 4)) { - number = (202 << 8) | (d->disk << 4) | d->partition; - } else if (d->disk < (1 << 20) && d->partition < (1 << 8)) { - number = (1 << 28) | (d ->disk << 8) | d->partition; + switch (vdev->type) { + case XEN_QDISK_VDEV_TYPE_DP: + case XEN_QDISK_VDEV_TYPE_XVD: + if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) { + number = (202 << 8) | (vdev->disk << 4) | vdev->partition; + } else if (vdev->disk < (1 << 20) && vdev->partition < (1 << 8)) { + number = (1 << 28) | (vdev ->disk << 8) | vdev->partition; } else { - error_setg(errp, "cannot use xvd encoding for d%up%u", d->disk, - d->partition); + error_setg(errp, "cannot use xvd encoding for d%up%u", + vdev->disk, vdev->partition); return NULL; } break; - case XEN_VDEV_TYPE_HD: - if ((d->disk == 0 || d->disk == 1) && d->partition < (1 << 4)) { - number = (3 << 8) | (d->disk << 6) | d->partition; - } else if ((d->disk == 2 || d->disk == 3) && - d->partition < (1 << 4)) { - number = (22 << 8) | ((d->disk - 2) << 6) | d->partition; + case XEN_QDISK_VDEV_TYPE_HD: + if ((vdev->disk == 0 || vdev->disk == 1) && + vdev->partition < (1 << 4)) { + number = (3 << 8) | (vdev->disk << 6) | vdev->partition; + } else if ((vdev->disk == 2 || vdev->disk == 3) && + vdev->partition < (1 << 4)) { + number = (22 << 8) | ((vdev->disk - 2) << 6) | vdev->partition; } else { - error_setg(errp, "cannot use hd encoding for d%up%u", d->disk, - d->partition); + error_setg(errp, "cannot use hd encoding for d%up%u", + vdev->disk, vdev->partition); return NULL; } break; - case XEN_VDEV_TYPE_SD: - if (d->disk < (1 << 4) && d->partition < (1 << 4)) { - number = (8 << 8) | (d->disk << 4) | d->partition; + case XEN_QDISK_VDEV_TYPE_SD: + if (vdev->disk < (1 << 4) && vdev->partition < (1 << 4)) { + number = (8 << 8) | (vdev->disk << 4) | vdev->partition; } else { - error_setg(errp, "cannot use sd encoding for d%up%u", d->disk, - d->partition); + error_setg(errp, "cannot use sd encoding for d%up%u", + vdev->disk, vdev->partition); return NULL; } break; @@ -628,13 +632,18 @@ static void xen_qdisk_realize(XenBackend *dev, Error **errp) unsigned int info; int64_t size; - trace_xen_qdisk_realize(d->disk, d->partition); + trace_xen_qdisk_realize(d->vdev.disk, d->vdev.partition); if (!d->conf.blk) { error_setg(errp, "drive property not set"); return; } + if (!d->vdev.valid) { + error_setg(errp, "vdev property not set"); + return; + } + if (!blk_is_inserted(d->conf.blk)) { error_setg(errp, "Device needs media, but drive is empty"); return; @@ -651,8 +660,7 @@ static void xen_qdisk_realize(XenBackend *dev, Error **errp) } dinfo = blk_legacy_dinfo(d->conf.blk); - if (dinfo && dinfo->media_cd) - is_cdrom = true; + is_cdrom = (dinfo && dinfo->media_cd); blkconf_blocksizes(&d->conf); @@ -678,7 +686,7 @@ static void xen_qdisk_realize(XenBackend *dev, Error **errp) xenstore_backend_printf(dev, "info", "%u", info); xenstore_frontend_printf(dev, "device-type", "%s", - dinfo->media_cd ? "cdrom" : "disk"); + is_cdrom ? "cdrom" : "disk"); size = blk_getlength(d->blk); xenstore_backend_printf(dev, "sector-size", "%u", @@ -717,7 +725,7 @@ static void xen_qdisk_initialize(XenBackend *dev, Error **errp) unsigned int ring_size; uint32_t *domids; - trace_xen_qdisk_initialize(d->disk, d->partition); + trace_xen_qdisk_initialize(d->vdev.disk, d->vdev.partition); if (xenstore_frontend_scanf(dev, "ring-page-order", "%u", &order) != 1) { @@ -864,7 +872,7 @@ static void xen_qdisk_disconnect(XenBackend *dev, Error **errp) { XenQdiskBackend *d = XEN_QDISK_BACKEND(dev); - trace_xen_qdisk_disconnect(d->disk, d->partition); + trace_xen_qdisk_disconnect(d->vdev.disk, d->vdev.partition); if (d->xeh) { aio_context_acquire(d->ctx); @@ -890,7 +898,7 @@ static void xen_qdisk_unrealize(XenBackend *dev, Error **errp) { XenQdiskBackend *d = XEN_QDISK_BACKEND(dev); - trace_xen_qdisk_unrealize(d->disk, d->partition); + trace_xen_qdisk_unrealize(d->vdev.disk, d->vdev.partition); while (!QLIST_EMPTY(&d->freelist)) { struct ioreq *ioreq = QLIST_FIRST(&d->freelist); @@ -904,66 +912,154 @@ static void xen_qdisk_unrealize(XenBackend *dev, Error **errp) qemu_bh_delete(d->bh); } -static void xen_vdev_get_type(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +static char *disk_to_vbd_name(unsigned int disk) { - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - int *ptr = qdev_get_prop_ptr(dev, prop); + unsigned int len = DIV_ROUND_UP(disk, 26); + char *name = g_malloc0(len + 1); - visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); + do { + name[len--] = 'a' + (disk % 26); + disk /= 26; + } while (disk != 0); + assert(len == 0); + + return name; } -static void xen_vdev_set_type(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +static void xen_qdisk_get_vdev(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; - int *ptr = qdev_get_prop_ptr(dev, prop); + XenQdiskVdev *vdev = qdev_get_prop_ptr(dev, prop); + char *str; - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); + switch (vdev->type) { + case XEN_QDISK_VDEV_TYPE_DP: + str = g_strdup_printf("d%up%u", vdev->disk, vdev->partition); + break; + + case XEN_QDISK_VDEV_TYPE_XVD: + case XEN_QDISK_VDEV_TYPE_HD: + case XEN_QDISK_VDEV_TYPE_SD: { + char *name = disk_to_vbd_name(vdev->disk); + + str = g_strdup_printf("%s%s%u", + (vdev->type == XEN_QDISK_VDEV_TYPE_XVD) ? + "xvd" : + (vdev->type == XEN_QDISK_VDEV_TYPE_HD) ? + "hd" : + "sd", + name, vdev->partition); + g_free(name); + break; + } + default: + error_setg(errp, "invalid vdev type"); return; } - visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); + visit_type_str(v, name, &str, errp); + g_free(str); } -static void xen_vdev_set_default_value_enum(Object *obj, - const Property *prop) +static unsigned int vbd_name_to_disk(char *name, char **endp) { - object_property_set_str(obj, - qapi_enum_lookup(prop->info->enum_table, - prop->defval.i), - prop->name, &error_abort); + unsigned int disk = 0; + + while (*name != '\0') { + if (!g_ascii_isalpha(*name) || !g_ascii_islower(*name)) + break; + + disk *= 26; + disk += *name++ - 'a'; + } + *endp = name; + + return disk; } + +static void xen_qdisk_set_vdev(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + XenQdiskVdev *vdev = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + char *str, *p, *end; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } -static QEnumLookup xen_vdev_type_lookup = { - .array = (const char *const[]) { - "xvd", - "hd", - "sd", - }, - .size = XEN_VDEV_TYPE__MAX, -}; + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + p = strchr(str, 'd'); + if (!p) { + goto invalid; + } -const PropertyInfo xen_qdisk_prop_type = { + *p++ = '\0'; + if (*str == '\0') { + vdev->type = XEN_QDISK_VDEV_TYPE_DP; + } else if (strcmp(str, "xv") == 0) { + vdev->type = XEN_QDISK_VDEV_TYPE_XVD; + } else if (strcmp(str, "h") == 0) { + vdev->type = XEN_QDISK_VDEV_TYPE_HD; + } else if (strcmp(str, "s") == 0) { + vdev->type = XEN_QDISK_VDEV_TYPE_SD; + } else { + goto invalid; + } + + if (vdev->type == XEN_QDISK_VDEV_TYPE_DP) { + vdev->disk = strtoul(p, &end, 10); + + if (*end == 'p') { + p = ++end; + if (*end == '\0') { + goto invalid; + } + } + } else { + vdev->disk = vbd_name_to_disk(p, &end); + } + + if (*end != '\0') { + p = end; + vdev->partition = strtoul(p, &end, 10); + if (*end != '\0') { + goto invalid; + } + } else { + vdev->partition = 0; + } + + g_free(str); + vdev->valid = true; + return; + +invalid: + error_setg(errp, "invalid vbd name"); + g_free(str); +} + +const PropertyInfo xen_qdisk_prop_vdev = { .name = "str", - .description = "xvd/hd/sd", - .enum_table = &xen_vdev_type_lookup, - .get = xen_vdev_get_type, - .set = xen_vdev_set_type, - .set_default_value = xen_vdev_set_default_value_enum, + .description = "Virtual Disk specifier: d*p*/xvd*/hd*/sd*", + .get = xen_qdisk_get_vdev, + .set = xen_qdisk_set_vdev, }; static Property xen_qdisk_props[] = { - DEFINE_PROP_SIGNED("vdev-type", XenQdiskBackend, type, 0, - xen_qdisk_prop_type, XenVdevType), - DEFINE_PROP_INT32("disk", XenQdiskBackend, - disk, -1), - DEFINE_PROP_UINT32("partition", XenQdiskBackend, - partition, 0), DEFINE_BLOCK_PROPERTIES(XenQdiskBackend, conf), + DEFINE_PROP("vdev", XenQdiskBackend, vdev, + xen_qdisk_prop_vdev, XenQdiskVdev), DEFINE_PROP_BOOL("discard-enable", XenQdiskBackend, discard_enable, false), DEFINE_PROP_UINT32("max-ring-page-order", XenQdiskBackend, @@ -999,3 +1095,8 @@ static void xen_qdisk_register_types(void) } type_init(xen_qdisk_register_types) + +void xen_qdisk_backend_create(char *path) +{ + fprintf(stderr, "%s: %s\n", __func__, path); +} diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 48f87035ef..72d4c1b10e 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -1373,14 +1373,13 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory) state->device_listener = xen_device_listener; device_listener_register(&state->device_listener); - xen_bus_init(); - /* Initialize backend core & drivers */ if (xen_be_init() != 0) { error_report("xen backend core setup failed"); goto err; } xen_be_register_common(); + xen_bus_init(); xen_read_physmap(state); /* Disable ACPI build because Xen handles it */ diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index 7445b506ac..a0ede6bd84 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -592,7 +592,7 @@ void xen_be_register_common(void) xen_be_register("console", &xen_console_ops); xen_be_register("vkbd", &xen_kbdmouse_ops); - xen_be_register("qdisk", &xen_blkdev_ops); + //xen_be_register("qdisk", &xen_blkdev_ops); #ifdef CONFIG_VIRTFS xen_be_register("9pfs", &xen_9pfs_ops); #endif diff --git a/hw/xen/xen_bus.c b/hw/xen/xen_bus.c index a83cf43e53..2f5958d93f 100644 --- a/hw/xen/xen_bus.c +++ b/hw/xen/xen_bus.c @@ -4,11 +4,14 @@ #include "hw/sysbus.h" #include "hw/boards.h" #include "qemu/log.h" +#include "qemu/option.h" +#include "qemu/config-file.h" #include "qapi/error.h" #include "hw/xen/xen.h" #include "hw/xen/xen_bus.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #include "trace.h" static domid_t xen_backend_id; @@ -68,7 +71,7 @@ static void xen_backend_vlog(XenBackend *d, const char *fmt, va_list ap) g_free(msg); } -static void xen_backend_log(XenBackend *d, const char *fmt, ...) +void xen_backend_log(XenBackend *d, const char *fmt, ...) { va_list ap; @@ -77,9 +80,6 @@ static void xen_backend_log(XenBackend *d, const char *fmt, ...) va_end(ap); } -#define XEN_BACKEND_LOG(d, fmt, ...) \ - xen_backend_log(d, "%s: " fmt, __func__, __VA_ARGS__) - static int xenstore_vprintf(struct xs_handle *xsh, char *node, const char *key, const char *fmt, va_list ap) { @@ -520,9 +520,49 @@ static void xen_backend_class_init(ObjectClass *klass, void *data) k->bus_type = TYPE_XEN_BUS; } +static void xen_backend_compat_scan(const char *type, + XenBackendCreate create) +{ + struct xs_handle *xsh; + char *path; + char **backend; + unsigned int i, count; + + xsh = xs_open(0); + if (!xsh) { + return; + } + + path = g_strdup_printf("backend/%s/%u", type, xen_domid); + backend = xs_directory(xsh, XBT_NULL, path, &count); + g_free(path); + + if (!backend) { + xs_close(xsh); + return; + } + + for (i = 0; i < count; i++) { + path = g_strdup_printf("backend/%s/%u/%s", type, xen_domid, + backend[i]); + + create(path); + g_free(path); + } + + free(backend); + + xs_close(xsh); +} + void xen_bus_init(void) { DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE); +#if 0 + DeviceState *qdisk; + QemuOpts *opts; + BlockBackend *blk; +#endif XenBus *b; qdev_init_nofail(dev); @@ -532,6 +572,25 @@ void xen_bus_init(void) /* Need a 'proper' way of getting current domid */ xen_backend_id = 0; + + xen_backend_compat_scan("qdisk", xen_qdisk_backend_create); + +#if 0 + opts = drive_def("id=extra"); + qemu_opt_set(opts, "file", "/root/disk.qcow2", &error_abort); + qemu_opt_set(opts, "media", "disk", &error_abort); + qemu_opt_set(opts, "format", "qcow2", &error_abort); + qemu_opt_set_bool(opts, BDRV_OPT_CACHE_WB, true, &error_abort); + qemu_opt_set_bool(opts, BDRV_OPT_READ_ONLY, false, &error_abort); + + drive_new(opts, IF_NONE); + + qdisk = qdev_create(BUS(b), "xen-qdisk"); + blk = blk_by_name("extra"); + qdev_prop_set_drive(qdisk, "drive", blk, &error_abort); + qdev_prop_set_int32(qdisk, "disk", 1); + qdev_init_nofail(qdisk); +#endif } static const TypeInfo xen_bridge_type_info = { diff --git a/include/hw/xen/xen_bus.h b/include/hw/xen/xen_bus.h index 370d220873..15613a5823 100644 --- a/include/hw/xen/xen_bus.h +++ b/include/hw/xen/xen_bus.h @@ -77,6 +77,11 @@ typedef struct XenBackendClass { #define TYPE_XEN_BRIDGE "xen-bridge" +typedef void (*XenBackendCreate)(char *path); + +void xen_qdisk_backend_create(char *path); + + void xen_bus_init(void); int xenstore_backend_printf(XenBackend *d, const char *key, @@ -86,4 +91,9 @@ int xenstore_frontend_printf(XenBackend *d, const char *key, int xenstore_frontend_scanf(XenBackend *d, const char *key, const char *fmt, ...); +void xen_backend_log(XenBackend *d, const char *fmt, ...); + +#define XEN_BACKEND_LOG(d, fmt, ...) \ + xen_backend_log(d, "%s: " fmt, __func__, __VA_ARGS__) + #endif