]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
stuff
authorPaul Durrant <paul.durrant@citrix.com>
Thu, 26 Apr 2018 14:54:29 +0000 (15:54 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Fri, 27 Apr 2018 12:52:54 +0000 (13:52 +0100)
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
hw/block/xen_qdisk.c
hw/i386/xen/xen-hvm.c
hw/xen/xen_backend.c
hw/xen/xen_bus.c
include/hw/xen/xen_bus.h

index 08dab165ec7234619306f9f2284af1a515e1cde8..c18ad8e1a8df6213675ebe11142378a3e81222d9 100644 (file)
 #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);
+}
index 48f87035ef80a7a9d9d9d4177035f12526e2b81c..72d4c1b10e5c149697ea4cc7fc3c9adb5b44e5db 100644 (file)
@@ -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 */
index 7445b506ac610dc35283f28072f0dca893d02dff..a0ede6bd84cd8790355ff58f74fba27624fe948b 100644 (file)
@@ -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
index a83cf43e53b447b076979ddf8993f2398996a6b9..2f5958d93fd470beab158a6fd228e3afea63d321 100644 (file)
@@ -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 = {
index 370d220873555834d12397b3dfc3db32f797d219..15613a5823f07b8be3435099f0819f93f436a039 100644 (file)
@@ -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