[Qemu-devel] Attempt to add support for NBD in MinGW

2013-10-28 Thread Or Goshen
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

2014-02-24 Thread Or Goshen
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

2014-02-24 Thread Or Goshen
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

2014-02-24 Thread Or Goshen
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

2014-02-24 Thread Or Goshen
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