]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
Add connect/disconnect code in qdisk
authorPaul Durrant <paul.durrant@citrix.com>
Wed, 25 Apr 2018 09:30:11 +0000 (10:30 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Thu, 26 Apr 2018 10:11:19 +0000 (11:11 +0100)
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
hw/block/xen_qdisk.c
hw/xen/xen_bus.c
include/hw/xen/xen_bus.h

index 4098333f1d359fe1ee3116a425d612c2c49403ed..459d3127895432db8cdcab157b32cc120779ae7a 100644 (file)
@@ -30,6 +30,20 @@ typedef struct XenQdiskBackend {
     bool discard_enable;
     unsigned int max_ring_page_order;
     BlockBackend *blk;
+    unsigned int nr_ring_ref;
+    uint32_t *ring_ref;
+    unsigned int protocol;
+    unsigned int max_requests;
+    xenevtchn_handle *xeh;
+    xenevtchn_port_or_error_t event_channel;
+    xengnttab_handle *xgth;
+    void *sring;
+    blkif_back_rings_t rings;
+
+    /* data path */
+    AioContext *ctx;
+    QEMUBH *bh;
+
 } XenQdiskBackend;
 
 static char *xen_qdisk_get_name(XenBackend *dev, Error **errp)
@@ -86,6 +100,10 @@ static char *xen_qdisk_get_name(XenBackend *dev, Error **errp)
     return g_strdup_printf("%u", number);
 }
 
+static void xen_qdisk_bh(void *opaque)
+{
+}
+
 static void xen_qdisk_realize(XenBackend *dev, Error **errp)
 {
     XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
@@ -133,25 +151,198 @@ static void xen_qdisk_realize(XenBackend *dev, Error **errp)
                             d->conf.logical_block_size);
     xenstore_backend_printf(dev, "sectors", "%lu",
                             size / d->conf.logical_block_size);
+
+    d->ctx = qemu_get_aio_context();
+    d->bh = aio_bh_new(d->ctx, xen_qdisk_bh, d);
+}
+
+static void xenevtchn_event_handler(void *opaque)
+{
+    XenQdiskBackend *d = opaque;
+    evtchn_port_t event_channel;
+
+    event_channel = xenevtchn_pending(d->xeh);
+    if (event_channel != d->event_channel)
+        return;
+
+    xenevtchn_unmask(d->xeh, event_channel);
+
+    qemu_bh_schedule(d->bh);
 }
 
 static void xen_qdisk_initialize(XenBackend *dev, Error **errp)
 {
+    XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
+    unsigned int order, ring_ref, event_channel;
+    char *protocol;
+    unsigned int i;
+    unsigned int ring_size;
+    uint32_t *domids;
+
+    if (xenstore_frontend_scanf(dev, "ring-page-order", "%u",
+                                &order) != 1) {
+        d->nr_ring_ref = 1u;
+        d->ring_ref = g_new(uint32_t, d->nr_ring_ref);
+
+        if (xenstore_frontend_scanf(dev, "ring-ref", "%u",
+                                    &ring_ref) != 1) {
+            error_setg(errp, "failed to read ring-ref");
+            return;
+        }
+
+        d->ring_ref[0] = ring_ref;
+    } else if (order <= d->max_ring_page_order) {
+        d->nr_ring_ref = 1u << order;
+        d->ring_ref = g_new(uint32_t, d->nr_ring_ref);
+
+        for (i = 0; i < d->nr_ring_ref; i++) {
+            const char *key = g_strdup_printf("ring-ref%u", i);
+
+            if (xenstore_frontend_scanf(dev, key, "%u", &ring_ref) != 1) {
+                error_setg(errp, "failed to read %s", key);
+                g_free((gpointer)key);
+                return;
+            }
+
+            d->ring_ref[i] = ring_ref;
+            g_free((gpointer)key);
+        }
+    } else {
+        error_setg(errp, "invalid ring-page-order (%d)", order);
+        return;
+    }
+
+    if (xenstore_frontend_scanf(dev, "event-channel", "%u",
+                                &event_channel) != 1) {
+        error_setg(errp, "failed to read event-channel");
+        return;
+    }
+
+    if (xenstore_frontend_scanf(dev, "protocol", "%ms", &protocol) != 1) {
+        d->protocol = BLKIF_PROTOCOL_NATIVE;
+    } else {
+        if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) {
+            d->protocol = BLKIF_PROTOCOL_X86_32;
+        } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) {
+            d->protocol = BLKIF_PROTOCOL_X86_64;
+        } else {
+            d->protocol = BLKIF_PROTOCOL_NATIVE;
+        }
+
+        free(protocol);
+    }
+
+    ring_size = XC_PAGE_SIZE * d->nr_ring_ref;
+    switch (d->protocol) {
+    case BLKIF_PROTOCOL_NATIVE:
+    {
+        d->max_requests = __CONST_RING_SIZE(blkif, ring_size);
+        break;
+    }
+    case BLKIF_PROTOCOL_X86_32:
+    {
+        d->max_requests = __CONST_RING_SIZE(blkif_x86_32, ring_size);
+        break;
+    }
+    case BLKIF_PROTOCOL_X86_64:
+    {
+        d->max_requests = __CONST_RING_SIZE(blkif_x86_64, ring_size);
+        break;
+    }
+    }
+
+    d->xgth = xengnttab_open(NULL, 0);
+    if (!d->xgth) {
+        error_setg_errno(errp, errno, "failed xengnttab_open");
+        return;
+    }
+
+    if (xengnttab_set_max_grants(d->xgth, d->nr_ring_ref)) {
+        error_setg_errno(errp, errno, "failed xengnttab_set_max_grants");
+        return;
+    }
+
+    domids = (uint32_t *)g_new0(domid_t, d->nr_ring_ref);
+    for (i = 0; i < d->nr_ring_ref; i++) {
+        domids[i] = dev->frontend_id;
+    }
+
+    d->sring = xengnttab_map_grant_refs(d->xgth, d->nr_ring_ref, domids,
+                                        d->ring_ref,
+                                        PROT_READ | PROT_WRITE);
+
+    g_free(domids);
+
+    if (!d->sring) {
+        error_setg_errno(errp, errno, "failed xengnttab_map_grant_refs");
+        return;
+    }
+
+    switch (d->protocol) {
+    case BLKIF_PROTOCOL_NATIVE:
+    {
+        blkif_sring_t *sring_native = d->sring;
+        BACK_RING_INIT(&d->rings.native, sring_native, ring_size);
+        break;
+    }
+    case BLKIF_PROTOCOL_X86_32:
+    {
+        blkif_x86_32_sring_t *sring_x86_32 = d->sring;
+
+        BACK_RING_INIT(&d->rings.x86_32_part, sring_x86_32, ring_size);
+        break;
+    }
+    case BLKIF_PROTOCOL_X86_64:
+    {
+        blkif_x86_64_sring_t *sring_x86_64 = d->sring;
+
+        BACK_RING_INIT(&d->rings.x86_64_part, sring_x86_64, ring_size);
+        break;
+    }
+    }
+
+    d->xeh = xenevtchn_open(NULL, 0);
+    if (!d->xeh) {
+        error_setg_errno(errp, errno, "failed xenevtchn_open");
+        return;
+    }
+
+    qemu_set_fd_handler(xenevtchn_fd(d->xeh), xenevtchn_event_handler,
+                        NULL, d);
+
+    d->event_channel = xenevtchn_bind_interdomain(d->xeh, dev->frontend_id,
+                                                  event_channel);
+    if (d->event_channel == -1) {
+        error_setg_errno(errp, errno, "failed xenevtchn_bind_interdomain");
+        return;
+    }
+
+    blk_set_aio_context(d->blk, d->ctx);
 }
 
 static void xen_qdisk_disconnect(XenBackend *dev, Error **errp)
 {
-}  
+    XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
 
-static void xen_qdisk_event(XenBackend *dev)
-{
+    aio_context_acquire(d->ctx);
+
+    xenevtchn_unbind(d->xeh, d->event_channel);
+    qemu_set_fd_handler(xenevtchn_fd(d->xeh), NULL, NULL, NULL);
+
+    aio_context_release(d->ctx);
+
+    xenevtchn_close(d->xeh);
+
+    xengnttab_unmap(d->xgth, d->sring, d->nr_ring_ref);
+
+    xengnttab_close(d->xgth);
 }  
 
 static void xen_qdisk_unrealize(XenBackend *dev, Error **errp)
 {
     XenQdiskBackend *d = XEN_QDISK_BACKEND(dev);
 
-    blockdev_mark_auto_del(d->blk);
+    qemu_bh_delete(d->bh);
 }
 
 static void xen_vdev_get_type(Object *obj, Visitor *v, const char *name,
@@ -226,12 +417,11 @@ static void xen_qdisk_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     XenBackendClass *k = XEN_BACKEND_CLASS(klass);
 
-    k->device = "bar";
+    k->device = "vbd";
     k->get_name = xen_qdisk_get_name;
     k->realize = xen_qdisk_realize;
     k->initialize = xen_qdisk_initialize;
     k->disconnect = xen_qdisk_disconnect;
-    k->event = xen_qdisk_event;
     k->unrealize = xen_qdisk_unrealize;
     dc->desc = "Xen Qdisk Backend";
     dc->props = xen_qdisk_props;
index edb48aa31528983376af9dd960de40974e2285cb..c1ed849b9c6e382ec62ba05758934cf319f232db 100644 (file)
@@ -405,7 +405,7 @@ static void xen_backend_realize(DeviceState *dev, Error **errp)
 
     d->xsh = xs_open(0);
     if (!d->xsh) {
-        error_setg(errp, "failed to open xenstore");
+        error_setg_errno(errp, errno, "failed xs_open");
         return;
     }
 
@@ -465,6 +465,7 @@ static void xen_backend_unrealize(DeviceState *dev, Error **errp)
     g_free(d->frontend_path);
     g_free(d->backend_path);
     
+    qemu_set_fd_handler(xs_fileno(d->xsh), NULL, NULL, NULL);
     xs_close(d->xsh);
 
     g_free(d->name);
index 3827b89917e489cc928323dc7cbdab9815681bde..370d220873555834d12397b3dfc3db32f797d219 100644 (file)
@@ -1,10 +1,7 @@
 #ifndef QEMU_XEN_BUS_H
 #define QEMU_XEN_BUS_H
 
-#include <xen/xen.h>
-#include <xen/io/xenbus.h>
-#include <xenstore.h>
-
+#include "hw/xen/xen_common.h"
 #include "hw/sysbus.h"
 #include "qemu/notify.h"
 
@@ -49,7 +46,6 @@ typedef void (*XenBackendConnected)(XenBackend *dev, Error **errp);
 typedef void (*XenBackendDisconnect)(XenBackend *dev, Error **errp);
 typedef void (*XenBackendReset)(XenBackend *dev, Error **errp);
 typedef void (*XenBackendUnrealize)(XenBackend *dev, Error **errp);
-typedef void (*XenBackendEvent)(XenBackend *dev);
 
 typedef struct XenBackendClass {
     /*< private >*/
@@ -63,7 +59,6 @@ typedef struct XenBackendClass {
     XenBackendDisconnect disconnect;
     XenBackendReset reset;
     XenBackendUnrealize unrealize;
-    XenBackendEvent event;
 } XenBackendClass;
 
 #define TYPE_XEN_BACKEND "xen-backend"