[Qemu-devel] Attempt to add support for NBD in MinGW
Hi, I try to add support for NBD in MinGW. Basicalyl this means adding support for win32 sockets to aio-win32.c. What I did was rewrite the file (attachment provided). problem here is that revents for the node related to the nbd socket is always 0 after g_poll() even when I see that data is returned from and nbd server (file attached). What am I doing wrong ? This was done against QEMU-1.6.0 Thanks, Or dumpfile.pcap Description: Binary data /* * QEMU aio implementation * * Copyright IBM, Corp. 2008 * * Authors: * Anthony Liguori * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * * Contributions after 2012-01-13 are licensed under the terms of the * GNU GPL, version 2 or (at your option) any later version. */ #include "qemu-common.h" #include "block/block.h" #include "qemu/queue.h" #include "qemu/sockets.h" struct AioHandler { GPollFD pfd; EventNotifier *e; int socket; GIOChannel *channel; IOHandler *io_read; IOHandler *io_write; EventNotifierHandler *io_notify; AioFlushHandler *io_flush; int deleted; int pollfds_idx; void *opaque; QLIST_ENTRY(AioHandler) node; }; static AioHandler *find_aio_handler(AioContext *ctx, int socket) { AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { if (node->socket == socket) if (!node->deleted) return node; } return NULL; } void aio_set_fd_handler(AioContext *ctx, int fd, IOHandler *io_read, IOHandler *io_write, AioFlushHandler *io_flush, void *opaque) { AioHandler *node; node = find_aio_handler(ctx, fd); /* Are we deleting the fd handler? */ if (!io_read && !io_write) { if (node) { g_source_remove_poll(&ctx->source, &node->pfd); g_io_channel_unref(node->channel); /* If the lock is held, just mark the node as deleted */ if (ctx->walking_handlers) { node->deleted = 1; node->pfd.revents = 0; } else { /* Otherwise, delete it for real. We can't just mark it as * deleted because deleted nodes are only cleaned up after * releasing the walking_handlers lock. */ QLIST_REMOVE(node, node); g_free(node); } } } else { if (node == NULL) { /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); node->socket = fd; node->channel = g_io_channel_win32_new_socket(fd); g_io_channel_win32_make_pollfd(node->channel, (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0)|(io_write ? G_IO_OUT | G_IO_ERR : 0), &node->pfd); QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); g_source_add_poll(&ctx->source, &node->pfd); } /* Update handler with latest information */ node->io_read = io_read; node->io_write = io_write; node->io_flush = io_flush; node->opaque = opaque; node->pollfds_idx = -1; } aio_notify(ctx); } void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, EventNotifierHandler *io_notify, AioFlushEventNotifierHandler *io_flush) { AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { if (node->e == notifier && !node->deleted) { break; } } /* Are we deleting the fd handler? */ if (!io_notify) { if (node) { g_source_remove_poll(&ctx->source, &node->pfd); /* If the lock is held, just mark the node as deleted */ if (ctx->walking_handlers) { node->deleted = 1; node->pfd.revents = 0; } else { /* Otherwise, delete it for real. We can't just mark it as * deleted because deleted nodes are only cleaned up after * releasing the walking_handlers lock. */ QLIST_REMOVE(node, node); g_free(node); } } } else { if (node == NULL) { /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); node->e = notifier; node->pfd.fd = (uintptr_t)event_notifier_get_handle(notifier); node->pfd.events = G_IO_IN; QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); g_source_add_poll(&ctx->source, &node->pfd); } /* Update handler with latest information */ node->io_notify = io_notify; node->io_flush = io_flush; } aio_notify(ctx); } bool aio_pending(AioContext *ctx) { AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { // HANDLE ? if (node->pfd.revents && node->io_notify) { return true; } // SOCKET ? int revents; revents = node->pfd.revents & node->pfd.events; if ((revents & G_I
[Qemu-devel] [PATCH] Support NBD client under win32/MinGW
From: Or Goshen --- aio-win32.c | 244 +-- block/Makefile.objs |4 +- block/nbd-client.h |2 +- include/block/aio.h |2 - include/block/nbd.h |2 +- main-loop.c |2 - nbd.c |4 +- qemu-coroutine-io.c |4 +- 8 files changed, 208 insertions(+), 56 deletions(-) diff --git a/aio-win32.c b/aio-win32.c index 23f4e5b..7f716b1 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -22,12 +22,76 @@ struct AioHandler { EventNotifier *e; +IOHandler *io_read; +IOHandler *io_write; EventNotifierHandler *io_notify; GPollFD pfd; int deleted; +void *opaque; QLIST_ENTRY(AioHandler) node; }; +void aio_set_fd_handler(AioContext *ctx, +int fd, +IOHandler *io_read, +IOHandler *io_write, +void *opaque) +{ + /* fd is a SOCKET in our case */ + AioHandler *node; + + QLIST_FOREACH(node, &ctx->aio_handlers, node) { + if (node->pfd.fd == fd && !node->deleted) + break; + } + + /* Are we deleting the fd handler? */ + if (!io_read && !io_write) { + if (node) { + /* If the lock is held, just mark the node as deleted */ + if (ctx->walking_handlers) { + node->deleted = 1; + node->pfd.revents = 0; + } else { + /* Otherwise, delete it for real. We can't just mark it as +* deleted because deleted nodes are only cleaned up after +* releasing the walking_handlers lock. +*/ + QLIST_REMOVE(node, node); + CloseHandle((HANDLE)node->e); + g_free(node); + } + } + } else { + if (node == NULL) { + /* Alloc and insert if it's not already there */ + node = g_malloc0(sizeof(AioHandler)); + node->pfd.fd = fd; + QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); + } + /* Create event */ + HANDLE event = WSACreateEvent(); + long lNetworkEvents = 0; + + if (node->io_read) + lNetworkEvents |= FD_READ; + if (node->io_write) + lNetworkEvents |= FD_WRITE; + + WSAEventSelect(node->pfd.fd, event, lNetworkEvents); + node->e = (EventNotifier *)event; + + /* Update handler with latest information */ + node->pfd.events = (io_read != NULL ? G_IO_IN : 0); + node->pfd.events |= (io_write != NULL ? G_IO_OUT : 0); + node->opaque = opaque; + node->io_read = io_read; + node->io_write = io_write; + } + + aio_notify(ctx); +} + void aio_set_event_notifier(AioContext *ctx, EventNotifier *e, EventNotifierHandler *io_notify) @@ -81,14 +145,88 @@ bool aio_pending(AioContext *ctx) AioHandler *node; QLIST_FOREACH(node, &ctx->aio_handlers, node) { + // HANDLE ? if (node->pfd.revents && node->io_notify) { return true; } + +// SOCKET ? + int revents; + + revents = node->pfd.revents & node->pfd.events; + if ((revents & G_IO_IN) && node->io_read) { + return true; + } + if ((revents & G_IO_OUT) && node->io_write) { + return true; + } } return false; } +static bool aio_dispatch(AioContext *ctx) +{ +AioHandler *node; +bool progress = false; + +/* + * We have to walk very carefully in case qemu_aio_set_fd_handler is + * called while we're walking. + */ +node = QLIST_FIRST(&ctx->aio_handlers); + while (node) { + AioHandler *tmp = node; + + ctx->walking_handlers++; + + if (!node->deleted) { + + // HANDLE ? + if (node->pfd.revents && node->io_notify) { + node->pfd.revents = 0; + node->io_notify(node->e); + + /* aio_notify() does not count as progress */ + if (node->e != &ctx->notifier) { + progress = true; +
[Qemu-devel] [PATCH] Add a command to QMP to list the supported devices
From: Or Goshen Was done on behalf of Intel Corp. --- qapi-schema.json | 26 ++ qdev-monitor.c | 28 qmp-commands.hx | 40 3 files changed, 94 insertions(+), 0 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index 05ced9d..cae1200 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -526,6 +526,32 @@ { 'command': 'query-commands', 'returns': ['CommandInfo'] } ## +# @DeviceInfo: +# +# Information about a device +# +# @name: The command name +# @bus: The bus it is connected to +# @alias: Device alias +# @desc: Description of the device +# +# Since: 1.6.0 +## +{ 'type': 'DeviceInfo', 'data': {'name': 'str', 'bus': 'str', 'alias': 'str', 'desc': 'str'} } + +## +# @query-devices: +# +# Return a list of supported devices +# +# Returns: A list of @DeviceInfo for all supported devices +# +# Since: 1.6.0 +## +{ 'command': 'query-devices', 'returns': ['DeviceInfo'] } + + +## # @EventInfo: # # Information about a QMP event diff --git a/qdev-monitor.c b/qdev-monitor.c index 1d3b68d..0a59fd9 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -644,6 +644,34 @@ void do_info_qtree(Monitor *mon, const QDict *qdict) qbus_print(mon, sysbus_get_default(), 0); } +static void qdev_list_devinfo(ObjectClass *klass, void *data) +{ +DeviceInfoList *e, **pret = data; +DeviceInfo *info; +DeviceClass *dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); +if (!dc) return; + +info = g_malloc0(sizeof(*info)); +info->name = g_strdup(object_class_get_name(klass)); +info->bus = g_strdup(dc->bus_type ? dc->bus_type : ""); +info->alias = g_strdup(qdev_class_has_alias(dc) ? qdev_class_get_alias(dc) : ""); +info->desc = g_strdup(dc->desc ? dc->desc : ""); + +e = g_malloc0(sizeof(*e)); +e->value = info; +e->next = *pret; +*pret = e; +} + +DeviceInfoList * qmp_query_devices(Error **errp) +{ +DeviceInfoList *list = NULL; + +object_class_foreach(qdev_list_devinfo, TYPE_DEVICE, false, &list); + +return list; +} + void do_info_qdm(Monitor *mon, const QDict *qdict) { qdev_print_devinfos(true); diff --git a/qmp-commands.hx b/qmp-commands.hx index cce6b81..be4451d 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1851,6 +1851,46 @@ EQMP }, SQMP +query-devices +-- + +List supported devices + +Each device is represented by a json-object, the returned value is a json-array +of all devices. + +Each json-object contain: + +- "name": device's name (json-string) +- "bus": bus the device connects to (json-string) +- "alias": device's alias (json-string) +- "desc": device's description (json-string) + +Example: + +-> { "execute": "query-devices" } +<- { + "return":[ + { +"name":"pci-bridge", +"bus":"PCI", +"alias":"", +"desc":"Standard PCI Bridge" + } + ] + } + +Note: This example has been shortened as the real response is too long. + +EQMP + +{ +.name = "query-devices", +.args_type = "", +.mhandler.cmd_new = qmp_marshal_input_query_devices, +}, + +SQMP query-events -- -- 1.7.9
Re: [Qemu-devel] [PATCH] Add a command to QMP to list the supported devices
You are correct. I need "-device ?" functionality for porting libguestfs to mingw On Mon, Feb 24, 2014 at 3:40 PM, Andreas Färber wrote: > Am 24.02.2014 10:31, schrieb Paolo Bonzini: > > Il 24/02/2014 10:23, Or Goshen ha scritto: > >> From: Or Goshen > >> > >> Was done on behalf of Intel Corp. > > > > Hi Or, > > > > you can use qom-list-types for this purpose. > > That can return a list of types, but there is no way to access the > DeviceClass-specific bus, alias, desc values, is there? > > It sounds to me as if they are trying to recreate the -device ? output > in machine-readable form. > > Regards, > Andreas > > -- > SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany > GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg > -- Or Goshen CTO Cerbercomm Mob: 972-50-9182418
Re: [Qemu-devel] [PATCH] Support NBD client under win32/MinGW
I never used/tested sheepdog under windows with my patch, so I wouldnt know if it doesnt have any additional bugs under windows. BTW, this patch is on behalf of Intel Corp On Mon, Feb 24, 2014 at 11:20 AM, Paolo Bonzini wrote: > Il 24/02/2014 10:13, Or Goshen ha scritto: > > >> + /* Create event */ >> + HANDLE event = WSACreateEvent(); >> + long lNetworkEvents = 0; >> + >> + if (node->io_read) >> + lNetworkEvents |= FD_READ; >> + if (node->io_write) >> + lNetworkEvents |= FD_WRITE; >> + >> + WSAEventSelect(node->pfd.fd, event, lNetworkEvents); >> + node->e = (EventNotifier *)event; >> > > As mentioned on IRC, I'd like you to try using the EventNotifier of the > AioContext. You shouldn't need any of these casts. > > > ifeq ($(CONFIG_POSIX),y) >> -block-obj-y += nbd.o nbd-client.o sheepdog.o >> +block-obj-y += nbd-client.o sheepdog.o >> > > nbd-client.c must be compiled on Windows, too. > > In fact I think you can just drop the ifeq/endif directives. > > > block-obj-$(CONFIG_LIBISCSI) += iscsi.o >> block-obj-$(CONFIG_CURL) += curl.o >> block-obj-$(CONFIG_RBD) += rbd.o >> > > Also, the patch has wrong indentation. We use 4 space indentation, and > never use tabs. > > Paolo > -- Or Goshen CTO Cerbercomm Mob: 972-50-9182418