From: Paul Durrant Date: Wed, 25 Apr 2018 09:30:11 +0000 (+0100) Subject: Add connect/disconnect code in qdisk X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=42ba09ca9a3eccd11b283676e5bcc787c5799618;p=people%2Fpauldu%2Fqemu.git Add connect/disconnect code in qdisk Signed-off-by: Paul Durrant --- diff --git a/hw/block/xen_qdisk.c b/hw/block/xen_qdisk.c index 4098333f1d..459d312789 100644 --- a/hw/block/xen_qdisk.c +++ b/hw/block/xen_qdisk.c @@ -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; diff --git a/hw/xen/xen_bus.c b/hw/xen/xen_bus.c index edb48aa315..c1ed849b9c 100644 --- a/hw/xen/xen_bus.c +++ b/hw/xen/xen_bus.c @@ -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); diff --git a/include/hw/xen/xen_bus.h b/include/hw/xen/xen_bus.h index 3827b89917..370d220873 100644 --- a/include/hw/xen/xen_bus.h +++ b/include/hw/xen/xen_bus.h @@ -1,10 +1,7 @@ #ifndef QEMU_XEN_BUS_H #define QEMU_XEN_BUS_H -#include -#include -#include - +#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"