All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
@ 2014-09-02 15:25 ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Here is a patchset containing an update on ivshmem specs documentation and
importing ivshmem server and client tools.
These tools have been written from scratch and are not related to what is
available in nahanni repository.
I put them in contrib/ directory as the qemu-doc.texi was already telling the
server was supposed to be there.

Changes since v3:
- first patch is untouched
- just restored the Reviewed-By Claudio in second patch
- following patches 3-8 take into account Stefan's comments
- patches 9-12 take into account Gonglei's comments
- patch 13 adjusts ivshmem-server default values
- last patch introduces a change in the ivshmem client-server protocol to
  check a protocol version at connect time

Changes since v2:
- fixed license issues in ivshmem client/server (I took hw/virtio/virtio-rng.c
  file as a reference).

Changes since v1:
- moved client/server import patch before doc update,
- tried to re-organise the ivshmem_device_spec.txt file based on Claudio
  comments (still not sure if the result is that great, comments welcome),
- incorporated comments from Claudio, Eric and Cam,
- added more details on the server <-> client messages exchange (but sorry, no
  ASCII art here).

By the way, there are still some functionnalities that need description (use of
ioeventfd, the lack of irqfd support) and some parts of the ivshmem code clearly
need cleanup. I will try to address this in future patches when these first
patches are ok.


-- 
David Marchand

David Marchand (14):
  contrib: add ivshmem client and server
  docs: update ivshmem device spec
  contrib/ivshmem-*: comply with QEMU coding style
  contrib/ivshmem-*: reuse qemu/queue.h
  contrib/ivshmem-*: switch to QEMU headers
  contrib/ivshmem-server: set client sockets as non blocking
  contrib/ivshmem-*: add missing const and static attrs
  contrib/ivshmem-*: plug client and server in QEMU top Makefile
  contrib/ivshmem-*: switch to g_malloc0/g_free
  contrib/ivshmem-server: fix mem leak on error
  contrib/ivshmem-*: rework error handling
  contrib/ivshmem-*: various fixes
  contrib/ivshmem-server: align server default parameter values
  ivshmem: add check on protocol version in QEMU

 Makefile                                |    8 +
 configure                               |    3 +
 contrib/ivshmem-client/ivshmem-client.c |  413 +++++++++++++++++++++++++++++++
 contrib/ivshmem-client/ivshmem-client.h |  240 ++++++++++++++++++
 contrib/ivshmem-client/main.c           |  237 ++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.c |  402 ++++++++++++++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.h |  187 ++++++++++++++
 contrib/ivshmem-server/main.c           |  243 ++++++++++++++++++
 docs/specs/ivshmem_device_spec.txt      |  127 +++++++---
 hw/misc/ivshmem.c                       |   43 +++-
 include/hw/misc/ivshmem.h               |   17 ++
 qemu-doc.texi                           |   10 +-
 12 files changed, 1887 insertions(+), 43 deletions(-)
 create mode 100644 contrib/ivshmem-client/ivshmem-client.c
 create mode 100644 contrib/ivshmem-client/ivshmem-client.h
 create mode 100644 contrib/ivshmem-client/main.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.h
 create mode 100644 contrib/ivshmem-server/main.c
 create mode 100644 include/hw/misc/ivshmem.h

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
@ 2014-09-02 15:25 ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Here is a patchset containing an update on ivshmem specs documentation and
importing ivshmem server and client tools.
These tools have been written from scratch and are not related to what is
available in nahanni repository.
I put them in contrib/ directory as the qemu-doc.texi was already telling the
server was supposed to be there.

Changes since v3:
- first patch is untouched
- just restored the Reviewed-By Claudio in second patch
- following patches 3-8 take into account Stefan's comments
- patches 9-12 take into account Gonglei's comments
- patch 13 adjusts ivshmem-server default values
- last patch introduces a change in the ivshmem client-server protocol to
  check a protocol version at connect time

Changes since v2:
- fixed license issues in ivshmem client/server (I took hw/virtio/virtio-rng.c
  file as a reference).

Changes since v1:
- moved client/server import patch before doc update,
- tried to re-organise the ivshmem_device_spec.txt file based on Claudio
  comments (still not sure if the result is that great, comments welcome),
- incorporated comments from Claudio, Eric and Cam,
- added more details on the server <-> client messages exchange (but sorry, no
  ASCII art here).

By the way, there are still some functionnalities that need description (use of
ioeventfd, the lack of irqfd support) and some parts of the ivshmem code clearly
need cleanup. I will try to address this in future patches when these first
patches are ok.


-- 
David Marchand

David Marchand (14):
  contrib: add ivshmem client and server
  docs: update ivshmem device spec
  contrib/ivshmem-*: comply with QEMU coding style
  contrib/ivshmem-*: reuse qemu/queue.h
  contrib/ivshmem-*: switch to QEMU headers
  contrib/ivshmem-server: set client sockets as non blocking
  contrib/ivshmem-*: add missing const and static attrs
  contrib/ivshmem-*: plug client and server in QEMU top Makefile
  contrib/ivshmem-*: switch to g_malloc0/g_free
  contrib/ivshmem-server: fix mem leak on error
  contrib/ivshmem-*: rework error handling
  contrib/ivshmem-*: various fixes
  contrib/ivshmem-server: align server default parameter values
  ivshmem: add check on protocol version in QEMU

 Makefile                                |    8 +
 configure                               |    3 +
 contrib/ivshmem-client/ivshmem-client.c |  413 +++++++++++++++++++++++++++++++
 contrib/ivshmem-client/ivshmem-client.h |  240 ++++++++++++++++++
 contrib/ivshmem-client/main.c           |  237 ++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.c |  402 ++++++++++++++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.h |  187 ++++++++++++++
 contrib/ivshmem-server/main.c           |  243 ++++++++++++++++++
 docs/specs/ivshmem_device_spec.txt      |  127 +++++++---
 hw/misc/ivshmem.c                       |   43 +++-
 include/hw/misc/ivshmem.h               |   17 ++
 qemu-doc.texi                           |   10 +-
 12 files changed, 1887 insertions(+), 43 deletions(-)
 create mode 100644 contrib/ivshmem-client/ivshmem-client.c
 create mode 100644 contrib/ivshmem-client/ivshmem-client.h
 create mode 100644 contrib/ivshmem-client/main.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.h
 create mode 100644 contrib/ivshmem-server/main.c
 create mode 100644 include/hw/misc/ivshmem.h

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH v4 01/14] contrib: add ivshmem client and server
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei, Olivier Matz

When using ivshmem devices, notifications between guests can be sent as
interrupts using a ivshmem-server (typical use described in documentation).
The client is provided as a debug tool.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/Makefile         |   29 +++
 contrib/ivshmem-client/ivshmem-client.c |  418 ++++++++++++++++++++++++++++++
 contrib/ivshmem-client/ivshmem-client.h |  238 ++++++++++++++++++
 contrib/ivshmem-client/main.c           |  246 ++++++++++++++++++
 contrib/ivshmem-server/Makefile         |   29 +++
 contrib/ivshmem-server/ivshmem-server.c |  420 +++++++++++++++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.h |  185 ++++++++++++++
 contrib/ivshmem-server/main.c           |  296 ++++++++++++++++++++++
 qemu-doc.texi                           |   10 +-
 9 files changed, 1868 insertions(+), 3 deletions(-)
 create mode 100644 contrib/ivshmem-client/Makefile
 create mode 100644 contrib/ivshmem-client/ivshmem-client.c
 create mode 100644 contrib/ivshmem-client/ivshmem-client.h
 create mode 100644 contrib/ivshmem-client/main.c
 create mode 100644 contrib/ivshmem-server/Makefile
 create mode 100644 contrib/ivshmem-server/ivshmem-server.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.h
 create mode 100644 contrib/ivshmem-server/main.c

diff --git a/contrib/ivshmem-client/Makefile b/contrib/ivshmem-client/Makefile
new file mode 100644
index 0000000..eee97c6
--- /dev/null
+++ b/contrib/ivshmem-client/Makefile
@@ -0,0 +1,29 @@
+# Copyright 6WIND S.A., 2014
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# (at your option) any later version.  See the COPYING file in the
+# top-level directory.
+
+S ?= $(CURDIR)
+O ?= $(CURDIR)
+
+CFLAGS += -Wall -Wextra -Werror -g
+LDFLAGS +=
+LDLIBS += -lrt
+
+VPATH = $(S)
+PROG = ivshmem-client
+OBJS := $(O)/ivshmem-client.o
+OBJS += $(O)/main.o
+
+$(O)/%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+$(O)/$(PROG): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: all
+all: $(O)/$(PROG)
+
+clean:
+	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
new file mode 100644
index 0000000..2166b64
--- /dev/null
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "ivshmem-client.h"
+
+/* log a message on stdout if verbose=1 */
+#define debug_log(client, fmt, ...) do { \
+        if ((client)->verbose) {         \
+            printf(fmt, ## __VA_ARGS__); \
+        }                                \
+    } while (0)
+
+/* read message from the unix socket */
+static int
+read_one_msg(struct ivshmem_client *client, long *index, int *fd)
+{
+    int ret;
+    struct msghdr msg;
+    struct iovec iov[1];
+    union {
+        struct cmsghdr cmsg;
+        char control[CMSG_SPACE(sizeof(int))];
+    } msg_control;
+    struct cmsghdr *cmsg;
+
+    iov[0].iov_base = index;
+    iov[0].iov_len = sizeof(*index);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &msg_control;
+    msg.msg_controllen = sizeof(msg_control);
+
+    ret = recvmsg(client->sock_fd, &msg, 0);
+    if (ret < 0) {
+        debug_log(client, "cannot read message: %s\n", strerror(errno));
+        return -1;
+    }
+    if (ret == 0) {
+        debug_log(client, "lost connection to server\n");
+        return -1;
+    }
+
+    *fd = -1;
+
+    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+
+        if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+            cmsg->cmsg_level != SOL_SOCKET ||
+            cmsg->cmsg_type != SCM_RIGHTS) {
+            continue;
+        }
+
+        memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
+    }
+
+    return 0;
+}
+
+/* free a peer when the server advertise a disconnection or when the
+ * client is freed */
+static void
+free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
+{
+    unsigned vector;
+
+    TAILQ_REMOVE(&client->peer_list, peer, next);
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        close(peer->vectors[vector]);
+    }
+
+    free(peer);
+}
+
+/* handle message coming from server (new peer, new vectors) */
+static int
+handle_server_msg(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    long peer_id;
+    int ret, fd;
+
+    ret = read_one_msg(client, &peer_id, &fd);
+    if (ret < 0) {
+        return -1;
+    }
+
+    /* can return a peer or the local client */
+    peer = ivshmem_client_search_peer(client, peer_id);
+
+    /* delete peer */
+    if (fd == -1) {
+
+        if (peer == NULL || peer == &client->local) {
+            debug_log(client, "receive delete for invalid peer %ld", peer_id);
+            return -1;
+        }
+
+        debug_log(client, "delete peer id = %ld\n", peer_id);
+        free_peer(client, peer);
+        return 0;
+    }
+
+    /* new peer */
+    if (peer == NULL) {
+        peer = malloc(sizeof(*peer));
+        if (peer == NULL) {
+            debug_log(client, "cannot allocate new peer\n");
+            return -1;
+        }
+        memset(peer, 0, sizeof(*peer));
+        peer->id = peer_id;
+        peer->vectors_count = 0;
+        TAILQ_INSERT_TAIL(&client->peer_list, peer, next);
+        debug_log(client, "new peer id = %ld\n", peer_id);
+    }
+
+    /* new vector */
+    debug_log(client, "  new vector %d (fd=%d) for peer id %ld\n",
+              peer->vectors_count, fd, peer->id);
+    peer->vectors[peer->vectors_count] = fd;
+    peer->vectors_count++;
+
+    return 0;
+}
+
+/* init a new ivshmem client */
+int
+ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
+                    ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
+                    int verbose)
+{
+    unsigned i;
+
+    memset(client, 0, sizeof(*client));
+
+    snprintf(client->unix_sock_path, sizeof(client->unix_sock_path),
+             "%s", unix_sock_path);
+
+    for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
+        client->local.vectors[i] = -1;
+    }
+
+    TAILQ_INIT(&client->peer_list);
+    client->local.id = -1;
+
+    client->notif_cb = notif_cb;
+    client->notif_arg = notif_arg;
+    client->verbose = verbose;
+
+    return 0;
+}
+
+/* create and connect to the unix socket */
+int
+ivshmem_client_connect(struct ivshmem_client *client)
+{
+    struct sockaddr_un sun;
+    int fd;
+    long tmp;
+
+    debug_log(client, "connect to client %s\n", client->unix_sock_path);
+
+    client->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (client->sock_fd < 0) {
+        debug_log(client, "cannot create socket: %s\n", strerror(errno));
+        return -1;
+    }
+
+    sun.sun_family = AF_UNIX;
+    snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", client->unix_sock_path);
+    if (connect(client->sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
+        debug_log(client, "cannot connect to %s: %s\n", sun.sun_path,
+                  strerror(errno));
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+
+    /* first, we expect our index + a fd == -1 */
+    if (read_one_msg(client, &client->local.id, &fd) < 0 ||
+        client->local.id < 0 || fd != -1) {
+        debug_log(client, "cannot read from server\n");
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+    debug_log(client, "our_id=%ld\n", client->local.id);
+
+    /* now, we expect shared mem fd + a -1 index, note that shm fd
+     * is not used */
+    if (read_one_msg(client, &tmp, &fd) < 0 ||
+        tmp != -1 || fd < 0) {
+        debug_log(client, "cannot read from server (2)\n");
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+    debug_log(client, "shm_fd=%d\n", fd);
+
+    return 0;
+}
+
+/* close connection to the server, and free all peer structures */
+void
+ivshmem_client_close(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    unsigned i;
+
+    debug_log(client, "close client\n");
+
+    while ((peer = TAILQ_FIRST(&client->peer_list)) != NULL) {
+        free_peer(client, peer);
+    }
+
+    close(client->sock_fd);
+    client->sock_fd = -1;
+    client->local.id = -1;
+    for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
+        client->local.vectors[i] = -1;
+    }
+}
+
+/* get the fd_set according to the unix socket and peer list */
+void
+ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+                       int *maxfd)
+{
+    int fd;
+    unsigned vector;
+
+    FD_SET(client->sock_fd, fds);
+    if (client->sock_fd >= *maxfd) {
+        *maxfd = client->sock_fd + 1;
+    }
+
+    for (vector = 0; vector < client->local.vectors_count; vector++) {
+        fd = client->local.vectors[vector];
+        FD_SET(fd, fds);
+        if (fd >= *maxfd) {
+            *maxfd = fd + 1;
+        }
+    }
+}
+
+/* handle events from eventfd: just print a message on notification */
+static int
+handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
+{
+    struct ivshmem_client_peer *peer;
+    uint64_t kick;
+    unsigned i;
+    int ret;
+
+    peer = &client->local;
+
+    for (i = 0; i < peer->vectors_count; i++) {
+        if (peer->vectors[i] >= maxfd || !FD_ISSET(peer->vectors[i], cur)) {
+            continue;
+        }
+
+        ret = read(peer->vectors[i], &kick, sizeof(kick));
+        if (ret < 0) {
+            return ret;
+        }
+        if (ret != sizeof(kick)) {
+            debug_log(client, "invalid read size = %d\n", ret);
+            errno = EINVAL;
+            return -1;
+        }
+        debug_log(client, "received event on fd %d vector %d: %ld\n",
+                  peer->vectors[i], i, kick);
+        if (client->notif_cb != NULL) {
+            client->notif_cb(client, peer, i, client->notif_arg);
+        }
+    }
+
+    return 0;
+}
+
+/* read and handle new messages on the given fd_set */
+int
+ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
+{
+    if (client->sock_fd < maxfd && FD_ISSET(client->sock_fd, fds) &&
+        handle_server_msg(client) < 0 && errno != EINTR) {
+        debug_log(client, "handle_server_msg() failed\n");
+        return -1;
+    } else if (handle_event(client, fds, maxfd) < 0 && errno != EINTR) {
+        debug_log(client, "handle_event() failed\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* send a notification on a vector of a peer */
+int
+ivshmem_client_notify(const struct ivshmem_client *client,
+                      const struct ivshmem_client_peer *peer, unsigned vector)
+{
+    uint64_t kick;
+    int fd;
+
+    if (vector > peer->vectors_count) {
+        debug_log(client, "invalid vector %u on peer %ld\n", vector, peer->id);
+        return -1;
+    }
+    fd = peer->vectors[vector];
+    debug_log(client, "notify peer %ld on vector %d, fd %d\n", peer->id, vector,
+              fd);
+
+    kick = 1;
+    if (write(fd, &kick, sizeof(kick)) != sizeof(kick)) {
+        fprintf(stderr, "could not write to %d: %s\n", peer->vectors[vector],
+                strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+/* send a notification to all vectors of a peer */
+int
+ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
+                                const struct ivshmem_client_peer *peer)
+{
+    unsigned vector;
+    int ret = 0;
+
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        if (ivshmem_client_notify(client, peer, vector) < 0) {
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
+/* send a notification to all peers */
+int
+ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    int ret = 0;
+
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        if (ivshmem_client_notify_all_vects(client, peer) < 0) {
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
+/* lookup peer from its id */
+struct ivshmem_client_peer *
+ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
+{
+    struct ivshmem_client_peer *peer;
+
+    if (peer_id == client->local.id) {
+        return &client->local;
+    }
+
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        if (peer->id == peer_id) {
+            return peer;
+        }
+    }
+    return NULL;
+}
+
+/* dump our info, the list of peers their vectors on stdout */
+void
+ivshmem_client_dump(const struct ivshmem_client *client)
+{
+    const struct ivshmem_client_peer *peer;
+    unsigned vector;
+
+    /* dump local infos */
+    peer = &client->local;
+    printf("our_id = %ld\n", peer->id);
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        printf("  vector %d is enabled (fd=%d)\n", vector,
+               peer->vectors[vector]);
+    }
+
+    /* dump peers */
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        printf("peer_id = %ld\n", peer->id);
+
+        for (vector = 0; vector < peer->vectors_count; vector++) {
+            printf("  vector %d is enabled (fd=%d)\n", vector,
+                   peer->vectors[vector]);
+        }
+    }
+}
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
new file mode 100644
index 0000000..d27222b
--- /dev/null
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_CLIENT_
+#define _IVSHMEM_CLIENT_
+
+/**
+ * This file provides helper to implement an ivshmem client. It is used
+ * on the host to ask QEMU to send an interrupt to an ivshmem PCI device in a
+ * guest. QEMU also implements an ivshmem client similar to this one, they both
+ * connect to an ivshmem server.
+ *
+ * A standalone ivshmem client based on this file is provided for debug/test
+ * purposes.
+ */
+
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+
+/**
+ * Maximum number of notification vectors supported by the client
+ */
+#define IVSHMEM_CLIENT_MAX_VECTORS 64
+
+/**
+ * Structure storing a peer
+ *
+ * Each time a client connects to an ivshmem server, it is advertised to
+ * all connected clients through the unix socket. When our ivshmem
+ * client receives a notification, it creates a ivshmem_client_peer
+ * structure to store the infos of this peer.
+ *
+ * This structure is also used to store the information of our own
+ * client in (struct ivshmem_client)->local.
+ */
+struct ivshmem_client_peer {
+    TAILQ_ENTRY(ivshmem_client_peer) next;    /**< next in list*/
+    long id;                                    /**< the id of the peer */
+    int vectors[IVSHMEM_CLIENT_MAX_VECTORS];  /**< one fd per vector */
+    unsigned vectors_count;                     /**< number of vectors */
+};
+TAILQ_HEAD(ivshmem_client_peer_list, ivshmem_client_peer);
+
+struct ivshmem_client;
+
+/**
+ * Typedef of callback function used when our ivshmem_client receives a
+ * notification from a peer.
+ */
+typedef void (*ivshmem_client_notif_cb_t)(
+    const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer,
+    unsigned vect, void *arg);
+
+/**
+ * Structure describing an ivshmem client
+ *
+ * This structure stores all information related to our client: the name
+ * of the server unix socket, the list of peers advertised by the
+ * server, our own client information, and a pointer the notification
+ * callback function used when we receive a notification from a peer.
+ */
+struct ivshmem_client {
+    char unix_sock_path[PATH_MAX];        /**< path to unix sock */
+    int sock_fd;                          /**< unix sock filedesc */
+
+    struct ivshmem_client_peer_list peer_list;  /**< list of peers */
+    struct ivshmem_client_peer local;   /**< our own infos */
+
+    ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
+    void *notif_arg;                      /**< notification argument */
+
+    int verbose;                          /**< true to enable debug */
+};
+
+/**
+ * Initialize an ivshmem client
+ *
+ * @param client
+ *   A pointer to an uninitialized ivshmem_client structure
+ * @param unix_sock_path
+ *   The pointer to the unix socket file name
+ * @param notif_cb
+ *   If not NULL, the pointer to the function to be called when we our
+ *   ivshmem_client receives a notification from a peer
+ * @param notif_arg
+ *   Opaque pointer given as-is to the notification callback function
+ * @param verbose
+ *   True to enable debug
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_client_init(struct ivshmem_client *client,
+    const char *unix_sock_path, ivshmem_client_notif_cb_t notif_cb,
+    void *notif_arg, int verbose);
+
+/**
+ * Connect to the server
+ *
+ * Connect to the server unix socket, and read the first initial
+ * messages sent by the server, giving the ID of the client and the file
+ * descriptor of the shared memory.
+ *
+ * @param client
+ *   The ivshmem client
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_client_connect(struct ivshmem_client *client);
+
+/**
+ * Close connection to the server and free all peer structures
+ *
+ * @param client
+ *   The ivshmem client
+ */
+void ivshmem_client_close(struct ivshmem_client *client);
+
+/**
+ * Fill a fd_set with file descriptors to be monitored
+ *
+ * This function will fill a fd_set with all file descriptors
+ * that must be polled (unix server socket and peers eventfd). The
+ * function will not initialize the fd_set, it is up to the caller
+ * to do this.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param fds
+ *   The fd_set to be updated
+ * @param maxfd
+ *   Must be set to the max file descriptor + 1 in fd_set. This value is
+ *   updated if this function adds a greated fd in fd_set.
+ */
+void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+                            int *maxfd);
+
+/**
+ * Read and handle new messages
+ *
+ * Given a fd_set filled by select(), handle incoming messages from
+ * server or peers.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param fds
+ *   The fd_set containing the file descriptors to be checked. Note
+ *   that file descriptors that are not related to our client are
+ *   ignored.
+ * @param maxfd
+ *   The maximum fd in fd_set, plus one.
+  *
+ * @return
+ *   0 on success, negative value on failure.
+ */
+int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
+    int maxfd);
+
+/**
+ * Send a notification to a vector of a peer
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer
+ *   The peer to be notified
+ * @param vector
+ *   The number of the vector
+ *
+ * @return
+ *   0 on success, and a negative error on failure.
+ */
+int ivshmem_client_notify(const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer, unsigned vector);
+
+/**
+ * Send a notification to all vectors of a peer
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer
+ *   The peer to be notified
+ *
+ * @return
+ *   0 on success, and a negative error on failure (at least one
+ *   notification failed).
+ */
+int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer);
+
+/**
+ * Broadcat a notification to all vectors of all peers
+ *
+ * @param client
+ *   The ivshmem client
+ *
+ * @return
+ *   0 on success, and a negative error on failure (at least one
+ *   notification failed).
+ */
+int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
+
+/**
+ * Search a peer from its identifier
+ *
+ * Return the peer structure from its peer_id. If the given peer_id is
+ * the local id, the function returns the local peer structure.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer_id
+ *   The identifier of the peer structure
+ *
+ * @return
+ *   The peer structure, or NULL if not found
+ */
+struct ivshmem_client_peer *
+ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
+
+/**
+ * Dump information of this ivshmem client on stdout
+ *
+ * Dump the id and the vectors of the given ivshmem client and the list
+ * of its peers and their vectors on stdout.
+ *
+ * @param client
+ *   The ivshmem client
+ */
+void ivshmem_client_dump(const struct ivshmem_client *client);
+
+#endif /* _IVSHMEM_CLIENT_ */
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
new file mode 100644
index 0000000..0d53f55
--- /dev/null
+++ b/contrib/ivshmem-client/main.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include "ivshmem-client.h"
+
+#define DEFAULT_VERBOSE        0
+#define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
+
+struct ivshmem_client_args {
+    int verbose;
+    char *unix_sock_path;
+};
+
+/* show usage and exit with given error code */
+static void
+usage(const char *name, int code)
+{
+    fprintf(stderr, "%s [opts]\n", name);
+    fprintf(stderr, "  -h: show this help\n");
+    fprintf(stderr, "  -v: verbose mode\n");
+    fprintf(stderr, "  -S <unix_sock_path>: path to the unix socket\n"
+                    "     to listen to.\n"
+                    "     default=%s\n", DEFAULT_UNIX_SOCK_PATH);
+    exit(code);
+}
+
+/* parse the program arguments, exit on error */
+static void
+parse_args(struct ivshmem_client_args *args, int argc, char *argv[])
+{
+    char c;
+
+    while ((c = getopt(argc, argv,
+                       "h"  /* help */
+                       "v"  /* verbose */
+                       "S:" /* unix_sock_path */
+                      )) != -1) {
+
+        switch (c) {
+        case 'h': /* help */
+            usage(argv[0], 0);
+            break;
+
+        case 'v': /* verbose */
+            args->verbose = 1;
+            break;
+
+        case 'S': /* unix_sock_path */
+            args->unix_sock_path = strdup(optarg);
+            break;
+
+        default:
+            usage(argv[0], 1);
+            break;
+        }
+    }
+}
+
+/* show command line help */
+static void
+cmdline_help(void)
+{
+    printf("dump: dump peers (including us)\n"
+           "int <peer> <vector>: notify one vector on a peer\n"
+           "int <peer> all: notify all vectors of a peer\n"
+           "int all: notify all vectors of all peers (excepting us)\n");
+}
+
+/* read stdin and handle commands */
+static int
+handle_stdin_command(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    char buf[128];
+    char *s, *token;
+    int ret;
+    int peer_id, vector;
+
+    memset(buf, 0, sizeof(buf));
+    ret = read(0, buf, sizeof(buf) - 1);
+    if (ret < 0) {
+        return -1;
+    }
+
+    s = buf;
+    while ((token = strsep(&s, "\n\r;")) != NULL) {
+        if (!strcmp(token, "")) {
+            continue;
+        }
+        if (!strcmp(token, "?")) {
+            cmdline_help();
+        }
+        if (!strcmp(token, "help")) {
+            cmdline_help();
+        } else if (!strcmp(token, "dump")) {
+            ivshmem_client_dump(client);
+        } else if (!strcmp(token, "int all")) {
+            ivshmem_client_notify_broadcast(client);
+        } else if (sscanf(token, "int %d %d", &peer_id, &vector) == 2) {
+            peer = ivshmem_client_search_peer(client, peer_id);
+            if (peer == NULL) {
+                printf("cannot find peer_id = %d\n", peer_id);
+                continue;
+            }
+            ivshmem_client_notify(client, peer, vector);
+        } else if (sscanf(token, "int %d all", &peer_id) == 1) {
+            peer = ivshmem_client_search_peer(client, peer_id);
+            if (peer == NULL) {
+                printf("cannot find peer_id = %d\n", peer_id);
+                continue;
+            }
+            ivshmem_client_notify_all_vects(client, peer);
+        } else {
+            printf("invalid command, type help\n");
+        }
+    }
+
+    printf("cmd> ");
+    fflush(stdout);
+    return 0;
+}
+
+/* listen on stdin (command line), on unix socket (notifications of new
+ * and dead peers), and on eventfd (IRQ request) */
+int
+poll_events(struct ivshmem_client *client)
+{
+    fd_set fds;
+    int ret, maxfd;
+
+    while (1) {
+
+        FD_ZERO(&fds);
+        FD_SET(0, &fds); /* add stdin in fd_set */
+        maxfd = 1;
+
+        ivshmem_client_get_fds(client, &fds, &maxfd);
+
+        ret = select(maxfd, &fds, NULL, NULL, NULL);
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            fprintf(stderr, "select error: %s\n", strerror(errno));
+            break;
+        }
+        if (ret == 0) {
+            continue;
+        }
+
+        if (FD_ISSET(0, &fds) &&
+            handle_stdin_command(client) < 0 && errno != EINTR) {
+            fprintf(stderr, "handle_stdin_command() failed\n");
+            break;
+        }
+
+        if (ivshmem_client_handle_fds(client, &fds, maxfd) < 0) {
+            fprintf(stderr, "ivshmem_client_handle_fds() failed\n");
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/* callback when we receive a notification (just display it) */
+void
+notification_cb(const struct ivshmem_client *client,
+                const struct ivshmem_client_peer *peer, unsigned vect,
+                void *arg)
+{
+    (void)client;
+    (void)arg;
+    printf("receive notification from peer_id=%ld vector=%d\n", peer->id, vect);
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct sigaction sa;
+    struct ivshmem_client client;
+    struct ivshmem_client_args args = {
+        .verbose = DEFAULT_VERBOSE,
+        .unix_sock_path = DEFAULT_UNIX_SOCK_PATH,
+    };
+
+    /* parse arguments, will exit on error */
+    parse_args(&args, argc, argv);
+
+    /* Ignore SIGPIPE, see this link for more info:
+     * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags = 0;
+    if (sigemptyset(&sa.sa_mask) == -1 ||
+        sigaction(SIGPIPE, &sa, 0) == -1) {
+        perror("failed to ignore SIGPIPE; sigaction");
+        return 1;
+    }
+
+    cmdline_help();
+    printf("cmd> ");
+    fflush(stdout);
+
+    if (ivshmem_client_init(&client, args.unix_sock_path, notification_cb,
+                            NULL, args.verbose) < 0) {
+        fprintf(stderr, "cannot init client\n");
+        return 1;
+    }
+
+    while (1) {
+        if (ivshmem_client_connect(&client) < 0) {
+            fprintf(stderr, "cannot connect to server, retry in 1 second\n");
+            sleep(1);
+            continue;
+        }
+
+        fprintf(stdout, "listen on server socket %d\n", client.sock_fd);
+
+        if (poll_events(&client) == 0) {
+            continue;
+        }
+
+        /* disconnected from server, reset all peers */
+        fprintf(stdout, "disconnected from server\n");
+
+        ivshmem_client_close(&client);
+    }
+
+    return 0;
+}
diff --git a/contrib/ivshmem-server/Makefile b/contrib/ivshmem-server/Makefile
new file mode 100644
index 0000000..26b4a72
--- /dev/null
+++ b/contrib/ivshmem-server/Makefile
@@ -0,0 +1,29 @@
+# Copyright 6WIND S.A., 2014
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# (at your option) any later version.  See the COPYING file in the
+# top-level directory.
+
+S ?= $(CURDIR)
+O ?= $(CURDIR)
+
+CFLAGS += -Wall -Wextra -Werror -g
+LDFLAGS +=
+LDLIBS += -lrt
+
+VPATH = $(S)
+PROG = ivshmem-server
+OBJS := $(O)/ivshmem-server.o
+OBJS += $(O)/main.o
+
+$(O)/%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+$(O)/$(PROG): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: all
+all: $(O)/$(PROG)
+
+clean:
+	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
new file mode 100644
index 0000000..f6497bb
--- /dev/null
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <fcntl.h>
+
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/eventfd.h>
+
+#include "ivshmem-server.h"
+
+/* log a message on stdout if verbose=1 */
+#define debug_log(server, fmt, ...) do { \
+        if ((server)->verbose) {         \
+            printf(fmt, ## __VA_ARGS__); \
+        }                                \
+    } while (0)
+
+/* browse the queue, allowing to remove/free the current element */
+#define    TAILQ_FOREACH_SAFE(var, var2, head, field)            \
+    for ((var) = TAILQ_FIRST((head)),                            \
+             (var2) = ((var) ? TAILQ_NEXT((var), field) : NULL); \
+         (var);                                                  \
+         (var) = (var2),                                         \
+             (var2) = ((var2) ? TAILQ_NEXT((var2), field) : NULL))
+
+/** maximum size of a huge page, used by ivshmem_ftruncate() */
+#define MAX_HUGEPAGE_SIZE (1024 * 1024 * 1024)
+
+/** default listen backlog (number of sockets not accepted) */
+#define IVSHMEM_SERVER_LISTEN_BACKLOG 10
+
+/* send message to a client unix socket */
+static int
+send_one_msg(int sock_fd, long peer_id, int fd)
+{
+    int ret;
+    struct msghdr msg;
+    struct iovec iov[1];
+    union {
+        struct cmsghdr cmsg;
+        char control[CMSG_SPACE(sizeof(int))];
+    } msg_control;
+    struct cmsghdr *cmsg;
+
+    iov[0].iov_base = &peer_id;
+    iov[0].iov_len = sizeof(peer_id);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+
+    /* if fd is specified, add it in a cmsg */
+    if (fd >= 0) {
+        msg.msg_control = &msg_control;
+        msg.msg_controllen = sizeof(msg_control);
+        cmsg = CMSG_FIRSTHDR(&msg);
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+        memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+    }
+
+    ret = sendmsg(sock_fd, &msg, 0);
+    if (ret <= 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/* free a peer when the server advertise a disconnection or when the
+ * server is freed */
+static void
+free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
+{
+    unsigned vector;
+    struct ivshmem_server_peer *other_peer;
+
+    debug_log(server, "free peer %ld\n", peer->id);
+    close(peer->sock_fd);
+    TAILQ_REMOVE(&server->peer_list, peer, next);
+
+    /* advertise the deletion to other peers */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        send_one_msg(other_peer->sock_fd, peer->id, -1);
+    }
+
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        close(peer->vectors[vector]);
+    }
+
+    free(peer);
+}
+
+/* send the peer id and the shm_fd just after a new client connection */
+static int
+send_initial_info(struct ivshmem_server *server,
+                  struct ivshmem_server_peer *peer)
+{
+    int ret;
+
+    /* send the peer id to the client */
+    ret = send_one_msg(peer->sock_fd, peer->id, -1);
+    if (ret < 0) {
+        debug_log(server, "cannot send peer id: %s\n", strerror(errno));
+        return -1;
+    }
+
+    /* send the shm_fd */
+    ret = send_one_msg(peer->sock_fd, -1, server->shm_fd);
+    if (ret < 0) {
+        debug_log(server, "cannot send shm fd: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+/* handle message on listening unix socket (new client connection) */
+static int
+handle_new_conn(struct ivshmem_server *server)
+{
+    struct ivshmem_server_peer *peer, *other_peer;
+    struct sockaddr_un unaddr;
+    socklen_t unaddr_len;
+    int newfd;
+    unsigned i;
+
+    /* accept the incoming connection */
+    unaddr_len = sizeof(unaddr);
+    newfd = accept(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len);
+    if (newfd < 0) {
+        debug_log(server, "cannot accept() %s\n", strerror(errno));
+        return -1;
+    }
+
+    debug_log(server, "accept()=%d\n", newfd);
+
+    /* allocate new structure for this peer */
+    peer = malloc(sizeof(*peer));
+    if (peer == NULL) {
+        debug_log(server, "cannot allocate new peer\n");
+        close(newfd);
+        return -1;
+    }
+
+    /* initialize the peer struct, one eventfd per vector */
+    memset(peer, 0, sizeof(*peer));
+    peer->sock_fd = newfd;
+
+    /* get an unused peer id */
+    while (ivshmem_server_search_peer(server, server->cur_id) != NULL) {
+        server->cur_id++;
+    }
+    peer->id = server->cur_id++;
+
+    /* create eventfd, one per vector */
+    peer->vectors_count = server->n_vectors;
+    for (i = 0; i < peer->vectors_count; i++) {
+        peer->vectors[i] = eventfd(0, 0);
+        if (peer->vectors[i] < 0) {
+            debug_log(server, "cannot create eventfd\n");
+            goto fail;
+        }
+    }
+
+    /* send peer id and shm fd */
+    if (send_initial_info(server, peer) < 0) {
+        debug_log(server, "cannot send initial info\n");
+        goto fail;
+    }
+
+    /* advertise the new peer to others */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        for (i = 0; i < peer->vectors_count; i++) {
+            send_one_msg(other_peer->sock_fd, peer->id, peer->vectors[i]);
+        }
+    }
+
+    /* advertise the other peers to the new one */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        for (i = 0; i < peer->vectors_count; i++) {
+            send_one_msg(peer->sock_fd, other_peer->id, other_peer->vectors[i]);
+        }
+    }
+
+    /* advertise the new peer to itself */
+    for (i = 0; i < peer->vectors_count; i++) {
+        send_one_msg(peer->sock_fd, peer->id, peer->vectors[i]);
+    }
+
+    TAILQ_INSERT_TAIL(&server->peer_list, peer, next);
+    debug_log(server, "new peer id = %ld\n", peer->id);
+    return 0;
+
+fail:
+    while (i--) {
+        close(peer->vectors[i]);
+    }
+    peer->sock_fd = -1;
+    close(newfd);
+    return -1;
+}
+
+/* Try to ftruncate a file to next power of 2 of shmsize.
+ * If it fails; all power of 2 above shmsize are tested until
+ * we reach the maximum huge page size. This is useful
+ * if the shm file is in a hugetlbfs that cannot be truncated to the
+ * shm_size value. */
+static int
+ivshmem_ftruncate(int fd, unsigned shmsize)
+{
+    int ret;
+
+    /* align shmsize to next power of 2 */
+    shmsize--;
+    shmsize |= shmsize >> 1;
+    shmsize |= shmsize >> 2;
+    shmsize |= shmsize >> 4;
+    shmsize |= shmsize >> 8;
+    shmsize |= shmsize >> 16;
+    shmsize++;
+
+    while (shmsize <= MAX_HUGEPAGE_SIZE) {
+        ret = ftruncate(fd, shmsize);
+        if (ret == 0) {
+            return ret;
+        }
+        shmsize *= 2;
+    }
+
+    return -1;
+}
+
+/* Init a new ivshmem server */
+int
+ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
+                    const char *shm_path, size_t shm_size, unsigned n_vectors,
+                    int verbose)
+{
+    memset(server, 0, sizeof(*server));
+
+    snprintf(server->unix_sock_path, sizeof(server->unix_sock_path),
+             "%s", unix_sock_path);
+    snprintf(server->shm_path, sizeof(server->shm_path),
+             "%s", shm_path);
+
+    server->shm_size = shm_size;
+    server->n_vectors = n_vectors;
+    server->verbose = verbose;
+
+    TAILQ_INIT(&server->peer_list);
+
+    return 0;
+}
+
+/* open shm, create and bind to the unix socket */
+int
+ivshmem_server_start(struct ivshmem_server *server)
+{
+    struct sockaddr_un sun;
+    int shm_fd, sock_fd;
+
+    /* open shm file */
+    shm_fd = shm_open(server->shm_path, O_CREAT|O_RDWR, S_IRWXU);
+    if (shm_fd < 0) {
+        fprintf(stderr, "cannot open shm file %s: %s\n", server->shm_path,
+                strerror(errno));
+        return -1;
+    }
+    if (ivshmem_ftruncate(shm_fd, server->shm_size) < 0) {
+        fprintf(stderr, "ftruncate(%s) failed: %s\n", server->shm_path,
+                strerror(errno));
+        return -1;
+    }
+
+    debug_log(server, "create & bind socket %s\n", server->unix_sock_path);
+
+    /* create the unix listening socket */
+    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock_fd < 0) {
+        debug_log(server, "cannot create socket: %s\n", strerror(errno));
+        close(shm_fd);
+        return -1;
+    }
+
+    sun.sun_family = AF_UNIX;
+    snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", server->unix_sock_path);
+    unlink(sun.sun_path);
+    if (bind(sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
+        debug_log(server, "cannot connect to %s: %s\n", sun.sun_path,
+                  strerror(errno));
+        close(sock_fd);
+        close(shm_fd);
+        return -1;
+    }
+
+    if (listen(sock_fd, IVSHMEM_SERVER_LISTEN_BACKLOG) < 0) {
+        debug_log(server, "listen() failed: %s\n", strerror(errno));
+        close(sock_fd);
+        close(shm_fd);
+        return -1;
+    }
+
+    server->sock_fd = sock_fd;
+    server->shm_fd = shm_fd;
+
+    return 0;
+}
+
+/* close connections to clients, the unix socket and the shm fd */
+void
+ivshmem_server_close(struct ivshmem_server *server)
+{
+    struct ivshmem_server_peer *peer;
+
+    debug_log(server, "close server\n");
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        free_peer(server, peer);
+    }
+
+    close(server->sock_fd);
+    close(server->shm_fd);
+    server->sock_fd = -1;
+    server->shm_fd = -1;
+}
+
+/* get the fd_set according to the unix socket and the peer list */
+void
+ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
+                       int *maxfd)
+{
+    struct ivshmem_server_peer *peer;
+
+    FD_SET(server->sock_fd, fds);
+    if (server->sock_fd >= *maxfd) {
+        *maxfd = server->sock_fd + 1;
+    }
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        FD_SET(peer->sock_fd, fds);
+        if (peer->sock_fd >= *maxfd) {
+            *maxfd = peer->sock_fd + 1;
+        }
+    }
+}
+
+/* process incoming messages on the sockets in fd_set */
+int
+ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
+{
+    struct ivshmem_server_peer *peer, *peer_next;
+
+    if (server->sock_fd < maxfd && FD_ISSET(server->sock_fd, fds) &&
+        handle_new_conn(server) < 0 && errno != EINTR) {
+        debug_log(server, "handle_new_conn() failed\n");
+        return -1;
+    }
+
+    TAILQ_FOREACH_SAFE(peer, peer_next, &server->peer_list, next) {
+        /* any message from a peer socket result in a close() */
+        debug_log(server, "peer->sock_fd=%d\n", peer->sock_fd);
+        if (peer->sock_fd < maxfd && FD_ISSET(peer->sock_fd, fds)) {
+            free_peer(server, peer);
+        }
+    }
+
+    return 0;
+}
+
+/* lookup peer from its id */
+struct ivshmem_server_peer *
+ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
+{
+    struct ivshmem_server_peer *peer;
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        if (peer->id == peer_id) {
+            return peer;
+        }
+    }
+    return NULL;
+}
+
+/* dump our info, the list of peers their vectors on stdout */
+void
+ivshmem_server_dump(const struct ivshmem_server *server)
+{
+    const struct ivshmem_server_peer *peer;
+    unsigned vector;
+
+    /* dump peers */
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        printf("peer_id = %ld\n", peer->id);
+
+        for (vector = 0; vector < peer->vectors_count; vector++) {
+            printf("  vector %d is enabled (fd=%d)\n", vector,
+                   peer->vectors[vector]);
+        }
+    }
+}
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
new file mode 100644
index 0000000..cd74bbf
--- /dev/null
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_SERVER_
+#define _IVSHMEM_SERVER_
+
+/**
+ * The ivshmem server is a daemon that creates a unix socket in listen
+ * mode. The ivshmem clients (qemu or ivshmem-client) connect to this
+ * unix socket. For each client, the server will create some eventfd
+ * (see EVENTFD(2)), one per vector. These fd are transmitted to all
+ * clients using the SCM_RIGHTS cmsg message. Therefore, each client is
+ * able to send a notification to another client without beeing
+ * "profixied" by the server.
+ *
+ * We use this mechanism to send interruptions between guests.
+ * qemu is able to transform an event on a eventfd into a PCI MSI-x
+ * interruption in the guest.
+ *
+ * The ivshmem server is also able to share the file descriptor
+ * associated to the ivshmem shared memory.
+ */
+
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+
+/**
+ * Maximum number of notification vectors supported by the server
+ */
+#define IVSHMEM_SERVER_MAX_VECTORS 64
+
+/**
+ * Structure storing a peer
+ *
+ * Each time a client connects to an ivshmem server, a new
+ * ivshmem_server_peer structure is created. This peer and all its
+ * vectors are advertised to all connected clients through the connected
+ * unix sockets.
+ */
+struct ivshmem_server_peer {
+    TAILQ_ENTRY(ivshmem_server_peer) next;    /**< next in list*/
+    int sock_fd;                                /**< connected unix sock */
+    long id;                                    /**< the id of the peer */
+    int vectors[IVSHMEM_SERVER_MAX_VECTORS];  /**< one fd per vector */
+    unsigned vectors_count;                     /**< number of vectors */
+};
+TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
+
+/**
+ * Structure describing an ivshmem server
+ *
+ * This structure stores all information related to our server: the name
+ * of the server unix socket and the list of connected peers.
+ */
+struct ivshmem_server {
+    char unix_sock_path[PATH_MAX];  /**< path to unix socket */
+    int sock_fd;                    /**< unix sock file descriptor */
+    char shm_path[PATH_MAX];        /**< path to shm */
+    size_t shm_size;                /**< size of shm */
+    int shm_fd;                     /**< shm file descriptor */
+    unsigned n_vectors;             /**< number of vectors */
+    long cur_id;                    /**< id to be given to next client */
+    int verbose;                    /**< true in verbose mode */
+    struct ivshmem_server_peer_list peer_list;  /**< list of peers */
+};
+
+/**
+ * Initialize an ivshmem server
+ *
+ * @param server
+ *   A pointer to an uninitialized ivshmem_server structure
+ * @param unix_sock_path
+ *   The pointer to the unix socket file name
+ * @param shm_path
+ *   Path to the shared memory. The path corresponds to a POSIX shm name.
+ *   To use a real file, for instance in a hugetlbfs, it is possible to
+ *   use /../../abspath/to/file.
+ * @param shm_size
+ *   Size of shared memory
+ * @param n_vectors
+ *   Number of interrupt vectors per client
+ * @param verbose
+ *   True to enable verbose mode
+ *
+ * @return
+ *   0 on success, negative value on error
+ */
+int
+ivshmem_server_init(struct ivshmem_server *server,
+    const char *unix_sock_path, const char *shm_path, size_t shm_size,
+    unsigned n_vectors, int verbose);
+
+/**
+ * Open the shm, then create and bind to the unix socket
+ *
+ * @param server
+ *   The pointer to the initialized ivshmem server structure
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_server_start(struct ivshmem_server *server);
+
+/**
+ * Close the server
+ *
+ * Close connections to all clients, close the unix socket and the
+ * shared memory file descriptor. The structure remains initialized, so
+ * it is possible to call ivshmem_server_start() again after a call to
+ * ivshmem_server_close().
+ *
+ * @param server
+ *   The ivshmem server
+ */
+void ivshmem_server_close(struct ivshmem_server *server);
+
+/**
+ * Fill a fd_set with file descriptors to be monitored
+ *
+ * This function will fill a fd_set with all file descriptors that must
+ * be polled (unix server socket and peers unix socket). The function
+ * will not initialize the fd_set, it is up to the caller to do it.
+ *
+ * @param server
+ *   The ivshmem server
+ * @param fds
+ *   The fd_set to be updated
+ * @param maxfd
+ *   Must be set to the max file descriptor + 1 in fd_set. This value is
+ *   updated if this function adds a greated fd in fd_set.
+ */
+void
+ivshmem_server_get_fds(const struct ivshmem_server *server,
+    fd_set *fds, int *maxfd);
+
+/**
+ * Read and handle new messages
+ *
+ * Given a fd_set (for instance filled by a call to select()), handle
+ * incoming messages from peers.
+ *
+ * @param server
+ *   The ivshmem server
+ * @param fds
+ *   The fd_set containing the file descriptors to be checked. Note
+ *   that file descriptors that are not related to our server are
+ *   ignored.
+ * @param maxfd
+ *   The maximum fd in fd_set, plus one.
+ *
+ * @return
+ *   0 on success, negative value on failure.
+ */
+int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
+    int maxfd);
+
+/**
+ * Search a peer from its identifier
+ *
+ * @param server
+ *   The ivshmem server
+ * @param peer_id
+ *   The identifier of the peer structure
+ *
+ * @return
+ *   The peer structure, or NULL if not found
+ */
+struct ivshmem_server_peer *
+ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
+
+/**
+ * Dump information of this ivshmem server and its peers on stdout
+ *
+ * @param server
+ *   The ivshmem server
+ */
+void ivshmem_server_dump(const struct ivshmem_server *server);
+
+#endif /* _IVSHMEM_SERVER_ */
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
new file mode 100644
index 0000000..36b7028
--- /dev/null
+++ b/contrib/ivshmem-server/main.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <getopt.h>
+
+#include "ivshmem-server.h"
+
+#define DEFAULT_VERBOSE        0
+#define DEFAULT_FOREGROUND     0
+#define DEFAULT_PID_FILE       "/var/run/ivshmem-server.pid"
+#define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
+#define DEFAULT_SHM_PATH       "ivshmem"
+#define DEFAULT_SHM_SIZE       (1024*1024)
+#define DEFAULT_N_VECTORS      16
+
+/* arguments given by the user */
+struct ivshmem_server_args {
+    int verbose;
+    int foreground;
+    char *pid_file;
+    char *unix_socket_path;
+    char *shm_path;
+    size_t shm_size;
+    unsigned n_vectors;
+};
+
+/* show usage and exit with given error code */
+static void
+usage(const char *name, int code)
+{
+    fprintf(stderr, "%s [opts]\n", name);
+    fprintf(stderr, "  -h: show this help\n");
+    fprintf(stderr, "  -v: verbose mode\n");
+    fprintf(stderr, "  -F: foreground mode (default is to daemonize)\n");
+    fprintf(stderr, "  -p <pid_file>: path to the PID file (used in daemon\n"
+                    "     mode only).\n"
+                    "     Default=%s\n", DEFAULT_SHM_PATH);
+    fprintf(stderr, "  -S <unix_socket_path>: path to the unix socket\n"
+                    "     to listen to.\n"
+                    "     Default=%s\n", DEFAULT_UNIX_SOCK_PATH);
+    fprintf(stderr, "  -m <shm_path>: path to the shared memory.\n"
+                    "     The path corresponds to a POSIX shm name. To use a\n"
+                    "     real file, for instance in a hugetlbfs, use\n"
+                    "     /../../abspath/to/file.\n"
+                    "     default=%s\n", DEFAULT_SHM_PATH);
+    fprintf(stderr, "  -l <size>: size of shared memory in bytes. The suffix\n"
+                    "     K, M and G can be used (ex: 1K means 1024).\n"
+                    "     default=%u\n", DEFAULT_SHM_SIZE);
+    fprintf(stderr, "  -n <n_vects>: number of vectors.\n"
+                    "     default=%u\n", DEFAULT_N_VECTORS);
+
+    exit(code);
+}
+
+/* parse the size of shm */
+static int
+parse_size(const char *val_str, size_t *val)
+{
+    char *endptr;
+    unsigned long long tmp;
+
+    errno = 0;
+    tmp = strtoull(val_str, &endptr, 0);
+    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
+        return -1;
+    }
+    if (endptr == val_str) {
+        return -1;
+    }
+    if (endptr[0] == 'K' && endptr[1] == '\0') {
+        tmp *= 1024;
+    } else if (endptr[0] == 'M' && endptr[1] == '\0') {
+        tmp *= 1024 * 1024;
+    } else if (endptr[0] == 'G' && endptr[1] == '\0') {
+        tmp *= 1024 * 1024 * 1024;
+    } else if (endptr[0] != '\0') {
+        return -1;
+    }
+
+    *val = tmp;
+    return 0;
+}
+
+/* parse an unsigned int */
+static int
+parse_uint(const char *val_str, unsigned *val)
+{
+    char *endptr;
+    unsigned long tmp;
+
+    errno = 0;
+    tmp = strtoul(val_str, &endptr, 0);
+    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
+        return -1;
+    }
+    if (endptr == val_str || endptr[0] != '\0') {
+        return -1;
+    }
+    *val = tmp;
+    return 0;
+}
+
+/* parse the program arguments, exit on error */
+static void
+parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
+{
+    char c;
+
+    while ((c = getopt(argc, argv,
+                       "h"  /* help */
+                       "v"  /* verbose */
+                       "F"  /* foreground */
+                       "p:" /* pid_file */
+                       "S:" /* unix_socket_path */
+                       "m:" /* shm_path */
+                       "l:" /* shm_size */
+                       "n:" /* n_vectors */
+                      )) != -1) {
+
+        switch (c) {
+        case 'h': /* help */
+            usage(argv[0], 0);
+            break;
+
+        case 'v': /* verbose */
+            args->verbose = 1;
+            break;
+
+        case 'F': /* foreground */
+            args->foreground = 1;
+            break;
+
+        case 'p': /* pid_file */
+            args->pid_file = strdup(optarg);
+            break;
+
+        case 'S': /* unix_socket_path */
+            args->unix_socket_path = strdup(optarg);
+            break;
+
+        case 'm': /* shm_path */
+            args->shm_path = strdup(optarg);
+            break;
+
+        case 'l': /* shm_size */
+            if (parse_size(optarg, &args->shm_size) < 0) {
+                fprintf(stderr, "cannot parse shm size\n");
+                usage(argv[0], 1);
+            }
+            break;
+
+        case 'n': /* n_vectors */
+            if (parse_uint(optarg, &args->n_vectors) < 0) {
+                fprintf(stderr, "cannot parse n_vectors\n");
+                usage(argv[0], 1);
+            }
+            break;
+
+        default:
+            usage(argv[0], 1);
+            break;
+        }
+    }
+
+    if (args->n_vectors > IVSHMEM_SERVER_MAX_VECTORS) {
+        fprintf(stderr, "too many requested vectors (max is %d)\n",
+                IVSHMEM_SERVER_MAX_VECTORS);
+        usage(argv[0], 1);
+    }
+
+    if (args->verbose == 1 && args->foreground == 0) {
+        fprintf(stderr, "cannot use verbose in daemon mode\n");
+        usage(argv[0], 1);
+    }
+}
+
+/* wait for events on listening server unix socket and connected client
+ * sockets */
+int
+poll_events(struct ivshmem_server *server)
+{
+    fd_set fds;
+    int ret, maxfd;
+
+    while (1) {
+
+        FD_ZERO(&fds);
+        maxfd = 0;
+        ivshmem_server_get_fds(server, &fds, &maxfd);
+
+        ret = select(maxfd, &fds, NULL, NULL, NULL);
+
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            fprintf(stderr, "select error: %s\n", strerror(errno));
+            break;
+        }
+        if (ret == 0) {
+            continue;
+        }
+
+        if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
+            fprintf(stderr, "ivshmem_server_handle_fds() failed\n");
+            break;
+        }
+    }
+
+    return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct ivshmem_server server;
+    struct sigaction sa;
+    struct ivshmem_server_args args = {
+        .verbose = DEFAULT_VERBOSE,
+        .foreground = DEFAULT_FOREGROUND,
+        .pid_file = DEFAULT_PID_FILE,
+        .unix_socket_path = DEFAULT_UNIX_SOCK_PATH,
+        .shm_path = DEFAULT_SHM_PATH,
+        .shm_size = DEFAULT_SHM_SIZE,
+        .n_vectors = DEFAULT_N_VECTORS,
+    };
+
+    /* parse arguments, will exit on error */
+    parse_args(&args, argc, argv);
+
+    /* Ignore SIGPIPE, see this link for more info:
+     * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags = 0;
+    if (sigemptyset(&sa.sa_mask) == -1 ||
+        sigaction(SIGPIPE, &sa, 0) == -1) {
+        perror("failed to ignore SIGPIPE; sigaction");
+        return 1;
+    }
+
+    /* init the ivshms structure */
+    if (ivshmem_server_init(&server, args.unix_socket_path, args.shm_path,
+                            args.shm_size, args.n_vectors, args.verbose) < 0) {
+        fprintf(stderr, "cannot init server\n");
+        return 1;
+    }
+
+    /* start the ivshmem server (open shm & unix socket) */
+    if (ivshmem_server_start(&server) < 0) {
+        fprintf(stderr, "cannot bind\n");
+        return 1;
+    }
+
+    /* daemonize if asked to */
+    if (!args.foreground) {
+        FILE *fp;
+
+        if (daemon(1, 1) < 0) {
+            fprintf(stderr, "cannot daemonize: %s\n", strerror(errno));
+            return 1;
+        }
+
+        /* write pid file */
+        fp = fopen(args.pid_file, "w");
+        if (fp == NULL) {
+            fprintf(stderr, "cannot write pid file: %s\n", strerror(errno));
+            return 1;
+        }
+
+        fprintf(fp, "%d\n", (int) getpid());
+        fclose(fp);
+    }
+
+    poll_events(&server);
+
+    fprintf(stdout, "server disconnected\n");
+    ivshmem_server_close(&server);
+
+    return 0;
+}
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 2b232ae..380d573 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1250,9 +1250,13 @@ is qemu.git/contrib/ivshmem-server.  An example syntax when using the shared
 memory server is:
 
 @example
-qemu-system-i386 -device ivshmem,size=<size in format accepted by -m>[,chardev=<id>]
-                 [,msi=on][,ioeventfd=on][,vectors=n][,role=peer|master]
-qemu-system-i386 -chardev socket,path=<path>,id=<id>
+# First start the ivshmem server once and for all
+ivshmem-server -p <pidfile> -S <path> -m <shm name> -l <shm size> -n <vectors n>
+
+# Then start your qemu instances with matching arguments
+qemu-system-i386 -device ivshmem,size=<shm size>,vectors=<vectors n>,chardev=<id>
+                 [,msi=on][,ioeventfd=on][,role=peer|master]
+                 -chardev socket,path=<path>,id=<id>
 @end example
 
 When using the server, the guest will be assigned a VM ID (>=0) that allows guests
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 01/14] contrib: add ivshmem client and server
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Olivier Matz, kvm, stefanha, claudio.fontana, armbru,
	arei.gonglei, pbonzini, jani.kokkonen, cam

When using ivshmem devices, notifications between guests can be sent as
interrupts using a ivshmem-server (typical use described in documentation).
The client is provided as a debug tool.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/Makefile         |   29 +++
 contrib/ivshmem-client/ivshmem-client.c |  418 ++++++++++++++++++++++++++++++
 contrib/ivshmem-client/ivshmem-client.h |  238 ++++++++++++++++++
 contrib/ivshmem-client/main.c           |  246 ++++++++++++++++++
 contrib/ivshmem-server/Makefile         |   29 +++
 contrib/ivshmem-server/ivshmem-server.c |  420 +++++++++++++++++++++++++++++++
 contrib/ivshmem-server/ivshmem-server.h |  185 ++++++++++++++
 contrib/ivshmem-server/main.c           |  296 ++++++++++++++++++++++
 qemu-doc.texi                           |   10 +-
 9 files changed, 1868 insertions(+), 3 deletions(-)
 create mode 100644 contrib/ivshmem-client/Makefile
 create mode 100644 contrib/ivshmem-client/ivshmem-client.c
 create mode 100644 contrib/ivshmem-client/ivshmem-client.h
 create mode 100644 contrib/ivshmem-client/main.c
 create mode 100644 contrib/ivshmem-server/Makefile
 create mode 100644 contrib/ivshmem-server/ivshmem-server.c
 create mode 100644 contrib/ivshmem-server/ivshmem-server.h
 create mode 100644 contrib/ivshmem-server/main.c

diff --git a/contrib/ivshmem-client/Makefile b/contrib/ivshmem-client/Makefile
new file mode 100644
index 0000000..eee97c6
--- /dev/null
+++ b/contrib/ivshmem-client/Makefile
@@ -0,0 +1,29 @@
+# Copyright 6WIND S.A., 2014
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# (at your option) any later version.  See the COPYING file in the
+# top-level directory.
+
+S ?= $(CURDIR)
+O ?= $(CURDIR)
+
+CFLAGS += -Wall -Wextra -Werror -g
+LDFLAGS +=
+LDLIBS += -lrt
+
+VPATH = $(S)
+PROG = ivshmem-client
+OBJS := $(O)/ivshmem-client.o
+OBJS += $(O)/main.o
+
+$(O)/%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+$(O)/$(PROG): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: all
+all: $(O)/$(PROG)
+
+clean:
+	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
new file mode 100644
index 0000000..2166b64
--- /dev/null
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "ivshmem-client.h"
+
+/* log a message on stdout if verbose=1 */
+#define debug_log(client, fmt, ...) do { \
+        if ((client)->verbose) {         \
+            printf(fmt, ## __VA_ARGS__); \
+        }                                \
+    } while (0)
+
+/* read message from the unix socket */
+static int
+read_one_msg(struct ivshmem_client *client, long *index, int *fd)
+{
+    int ret;
+    struct msghdr msg;
+    struct iovec iov[1];
+    union {
+        struct cmsghdr cmsg;
+        char control[CMSG_SPACE(sizeof(int))];
+    } msg_control;
+    struct cmsghdr *cmsg;
+
+    iov[0].iov_base = index;
+    iov[0].iov_len = sizeof(*index);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &msg_control;
+    msg.msg_controllen = sizeof(msg_control);
+
+    ret = recvmsg(client->sock_fd, &msg, 0);
+    if (ret < 0) {
+        debug_log(client, "cannot read message: %s\n", strerror(errno));
+        return -1;
+    }
+    if (ret == 0) {
+        debug_log(client, "lost connection to server\n");
+        return -1;
+    }
+
+    *fd = -1;
+
+    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+
+        if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+            cmsg->cmsg_level != SOL_SOCKET ||
+            cmsg->cmsg_type != SCM_RIGHTS) {
+            continue;
+        }
+
+        memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
+    }
+
+    return 0;
+}
+
+/* free a peer when the server advertise a disconnection or when the
+ * client is freed */
+static void
+free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
+{
+    unsigned vector;
+
+    TAILQ_REMOVE(&client->peer_list, peer, next);
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        close(peer->vectors[vector]);
+    }
+
+    free(peer);
+}
+
+/* handle message coming from server (new peer, new vectors) */
+static int
+handle_server_msg(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    long peer_id;
+    int ret, fd;
+
+    ret = read_one_msg(client, &peer_id, &fd);
+    if (ret < 0) {
+        return -1;
+    }
+
+    /* can return a peer or the local client */
+    peer = ivshmem_client_search_peer(client, peer_id);
+
+    /* delete peer */
+    if (fd == -1) {
+
+        if (peer == NULL || peer == &client->local) {
+            debug_log(client, "receive delete for invalid peer %ld", peer_id);
+            return -1;
+        }
+
+        debug_log(client, "delete peer id = %ld\n", peer_id);
+        free_peer(client, peer);
+        return 0;
+    }
+
+    /* new peer */
+    if (peer == NULL) {
+        peer = malloc(sizeof(*peer));
+        if (peer == NULL) {
+            debug_log(client, "cannot allocate new peer\n");
+            return -1;
+        }
+        memset(peer, 0, sizeof(*peer));
+        peer->id = peer_id;
+        peer->vectors_count = 0;
+        TAILQ_INSERT_TAIL(&client->peer_list, peer, next);
+        debug_log(client, "new peer id = %ld\n", peer_id);
+    }
+
+    /* new vector */
+    debug_log(client, "  new vector %d (fd=%d) for peer id %ld\n",
+              peer->vectors_count, fd, peer->id);
+    peer->vectors[peer->vectors_count] = fd;
+    peer->vectors_count++;
+
+    return 0;
+}
+
+/* init a new ivshmem client */
+int
+ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
+                    ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
+                    int verbose)
+{
+    unsigned i;
+
+    memset(client, 0, sizeof(*client));
+
+    snprintf(client->unix_sock_path, sizeof(client->unix_sock_path),
+             "%s", unix_sock_path);
+
+    for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
+        client->local.vectors[i] = -1;
+    }
+
+    TAILQ_INIT(&client->peer_list);
+    client->local.id = -1;
+
+    client->notif_cb = notif_cb;
+    client->notif_arg = notif_arg;
+    client->verbose = verbose;
+
+    return 0;
+}
+
+/* create and connect to the unix socket */
+int
+ivshmem_client_connect(struct ivshmem_client *client)
+{
+    struct sockaddr_un sun;
+    int fd;
+    long tmp;
+
+    debug_log(client, "connect to client %s\n", client->unix_sock_path);
+
+    client->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (client->sock_fd < 0) {
+        debug_log(client, "cannot create socket: %s\n", strerror(errno));
+        return -1;
+    }
+
+    sun.sun_family = AF_UNIX;
+    snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", client->unix_sock_path);
+    if (connect(client->sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
+        debug_log(client, "cannot connect to %s: %s\n", sun.sun_path,
+                  strerror(errno));
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+
+    /* first, we expect our index + a fd == -1 */
+    if (read_one_msg(client, &client->local.id, &fd) < 0 ||
+        client->local.id < 0 || fd != -1) {
+        debug_log(client, "cannot read from server\n");
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+    debug_log(client, "our_id=%ld\n", client->local.id);
+
+    /* now, we expect shared mem fd + a -1 index, note that shm fd
+     * is not used */
+    if (read_one_msg(client, &tmp, &fd) < 0 ||
+        tmp != -1 || fd < 0) {
+        debug_log(client, "cannot read from server (2)\n");
+        close(client->sock_fd);
+        client->sock_fd = -1;
+        return -1;
+    }
+    debug_log(client, "shm_fd=%d\n", fd);
+
+    return 0;
+}
+
+/* close connection to the server, and free all peer structures */
+void
+ivshmem_client_close(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    unsigned i;
+
+    debug_log(client, "close client\n");
+
+    while ((peer = TAILQ_FIRST(&client->peer_list)) != NULL) {
+        free_peer(client, peer);
+    }
+
+    close(client->sock_fd);
+    client->sock_fd = -1;
+    client->local.id = -1;
+    for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
+        client->local.vectors[i] = -1;
+    }
+}
+
+/* get the fd_set according to the unix socket and peer list */
+void
+ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+                       int *maxfd)
+{
+    int fd;
+    unsigned vector;
+
+    FD_SET(client->sock_fd, fds);
+    if (client->sock_fd >= *maxfd) {
+        *maxfd = client->sock_fd + 1;
+    }
+
+    for (vector = 0; vector < client->local.vectors_count; vector++) {
+        fd = client->local.vectors[vector];
+        FD_SET(fd, fds);
+        if (fd >= *maxfd) {
+            *maxfd = fd + 1;
+        }
+    }
+}
+
+/* handle events from eventfd: just print a message on notification */
+static int
+handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
+{
+    struct ivshmem_client_peer *peer;
+    uint64_t kick;
+    unsigned i;
+    int ret;
+
+    peer = &client->local;
+
+    for (i = 0; i < peer->vectors_count; i++) {
+        if (peer->vectors[i] >= maxfd || !FD_ISSET(peer->vectors[i], cur)) {
+            continue;
+        }
+
+        ret = read(peer->vectors[i], &kick, sizeof(kick));
+        if (ret < 0) {
+            return ret;
+        }
+        if (ret != sizeof(kick)) {
+            debug_log(client, "invalid read size = %d\n", ret);
+            errno = EINVAL;
+            return -1;
+        }
+        debug_log(client, "received event on fd %d vector %d: %ld\n",
+                  peer->vectors[i], i, kick);
+        if (client->notif_cb != NULL) {
+            client->notif_cb(client, peer, i, client->notif_arg);
+        }
+    }
+
+    return 0;
+}
+
+/* read and handle new messages on the given fd_set */
+int
+ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
+{
+    if (client->sock_fd < maxfd && FD_ISSET(client->sock_fd, fds) &&
+        handle_server_msg(client) < 0 && errno != EINTR) {
+        debug_log(client, "handle_server_msg() failed\n");
+        return -1;
+    } else if (handle_event(client, fds, maxfd) < 0 && errno != EINTR) {
+        debug_log(client, "handle_event() failed\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* send a notification on a vector of a peer */
+int
+ivshmem_client_notify(const struct ivshmem_client *client,
+                      const struct ivshmem_client_peer *peer, unsigned vector)
+{
+    uint64_t kick;
+    int fd;
+
+    if (vector > peer->vectors_count) {
+        debug_log(client, "invalid vector %u on peer %ld\n", vector, peer->id);
+        return -1;
+    }
+    fd = peer->vectors[vector];
+    debug_log(client, "notify peer %ld on vector %d, fd %d\n", peer->id, vector,
+              fd);
+
+    kick = 1;
+    if (write(fd, &kick, sizeof(kick)) != sizeof(kick)) {
+        fprintf(stderr, "could not write to %d: %s\n", peer->vectors[vector],
+                strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+/* send a notification to all vectors of a peer */
+int
+ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
+                                const struct ivshmem_client_peer *peer)
+{
+    unsigned vector;
+    int ret = 0;
+
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        if (ivshmem_client_notify(client, peer, vector) < 0) {
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
+/* send a notification to all peers */
+int
+ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    int ret = 0;
+
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        if (ivshmem_client_notify_all_vects(client, peer) < 0) {
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
+/* lookup peer from its id */
+struct ivshmem_client_peer *
+ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
+{
+    struct ivshmem_client_peer *peer;
+
+    if (peer_id == client->local.id) {
+        return &client->local;
+    }
+
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        if (peer->id == peer_id) {
+            return peer;
+        }
+    }
+    return NULL;
+}
+
+/* dump our info, the list of peers their vectors on stdout */
+void
+ivshmem_client_dump(const struct ivshmem_client *client)
+{
+    const struct ivshmem_client_peer *peer;
+    unsigned vector;
+
+    /* dump local infos */
+    peer = &client->local;
+    printf("our_id = %ld\n", peer->id);
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        printf("  vector %d is enabled (fd=%d)\n", vector,
+               peer->vectors[vector]);
+    }
+
+    /* dump peers */
+    TAILQ_FOREACH(peer, &client->peer_list, next) {
+        printf("peer_id = %ld\n", peer->id);
+
+        for (vector = 0; vector < peer->vectors_count; vector++) {
+            printf("  vector %d is enabled (fd=%d)\n", vector,
+                   peer->vectors[vector]);
+        }
+    }
+}
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
new file mode 100644
index 0000000..d27222b
--- /dev/null
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_CLIENT_
+#define _IVSHMEM_CLIENT_
+
+/**
+ * This file provides helper to implement an ivshmem client. It is used
+ * on the host to ask QEMU to send an interrupt to an ivshmem PCI device in a
+ * guest. QEMU also implements an ivshmem client similar to this one, they both
+ * connect to an ivshmem server.
+ *
+ * A standalone ivshmem client based on this file is provided for debug/test
+ * purposes.
+ */
+
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+
+/**
+ * Maximum number of notification vectors supported by the client
+ */
+#define IVSHMEM_CLIENT_MAX_VECTORS 64
+
+/**
+ * Structure storing a peer
+ *
+ * Each time a client connects to an ivshmem server, it is advertised to
+ * all connected clients through the unix socket. When our ivshmem
+ * client receives a notification, it creates a ivshmem_client_peer
+ * structure to store the infos of this peer.
+ *
+ * This structure is also used to store the information of our own
+ * client in (struct ivshmem_client)->local.
+ */
+struct ivshmem_client_peer {
+    TAILQ_ENTRY(ivshmem_client_peer) next;    /**< next in list*/
+    long id;                                    /**< the id of the peer */
+    int vectors[IVSHMEM_CLIENT_MAX_VECTORS];  /**< one fd per vector */
+    unsigned vectors_count;                     /**< number of vectors */
+};
+TAILQ_HEAD(ivshmem_client_peer_list, ivshmem_client_peer);
+
+struct ivshmem_client;
+
+/**
+ * Typedef of callback function used when our ivshmem_client receives a
+ * notification from a peer.
+ */
+typedef void (*ivshmem_client_notif_cb_t)(
+    const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer,
+    unsigned vect, void *arg);
+
+/**
+ * Structure describing an ivshmem client
+ *
+ * This structure stores all information related to our client: the name
+ * of the server unix socket, the list of peers advertised by the
+ * server, our own client information, and a pointer the notification
+ * callback function used when we receive a notification from a peer.
+ */
+struct ivshmem_client {
+    char unix_sock_path[PATH_MAX];        /**< path to unix sock */
+    int sock_fd;                          /**< unix sock filedesc */
+
+    struct ivshmem_client_peer_list peer_list;  /**< list of peers */
+    struct ivshmem_client_peer local;   /**< our own infos */
+
+    ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
+    void *notif_arg;                      /**< notification argument */
+
+    int verbose;                          /**< true to enable debug */
+};
+
+/**
+ * Initialize an ivshmem client
+ *
+ * @param client
+ *   A pointer to an uninitialized ivshmem_client structure
+ * @param unix_sock_path
+ *   The pointer to the unix socket file name
+ * @param notif_cb
+ *   If not NULL, the pointer to the function to be called when we our
+ *   ivshmem_client receives a notification from a peer
+ * @param notif_arg
+ *   Opaque pointer given as-is to the notification callback function
+ * @param verbose
+ *   True to enable debug
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_client_init(struct ivshmem_client *client,
+    const char *unix_sock_path, ivshmem_client_notif_cb_t notif_cb,
+    void *notif_arg, int verbose);
+
+/**
+ * Connect to the server
+ *
+ * Connect to the server unix socket, and read the first initial
+ * messages sent by the server, giving the ID of the client and the file
+ * descriptor of the shared memory.
+ *
+ * @param client
+ *   The ivshmem client
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_client_connect(struct ivshmem_client *client);
+
+/**
+ * Close connection to the server and free all peer structures
+ *
+ * @param client
+ *   The ivshmem client
+ */
+void ivshmem_client_close(struct ivshmem_client *client);
+
+/**
+ * Fill a fd_set with file descriptors to be monitored
+ *
+ * This function will fill a fd_set with all file descriptors
+ * that must be polled (unix server socket and peers eventfd). The
+ * function will not initialize the fd_set, it is up to the caller
+ * to do this.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param fds
+ *   The fd_set to be updated
+ * @param maxfd
+ *   Must be set to the max file descriptor + 1 in fd_set. This value is
+ *   updated if this function adds a greated fd in fd_set.
+ */
+void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+                            int *maxfd);
+
+/**
+ * Read and handle new messages
+ *
+ * Given a fd_set filled by select(), handle incoming messages from
+ * server or peers.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param fds
+ *   The fd_set containing the file descriptors to be checked. Note
+ *   that file descriptors that are not related to our client are
+ *   ignored.
+ * @param maxfd
+ *   The maximum fd in fd_set, plus one.
+  *
+ * @return
+ *   0 on success, negative value on failure.
+ */
+int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
+    int maxfd);
+
+/**
+ * Send a notification to a vector of a peer
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer
+ *   The peer to be notified
+ * @param vector
+ *   The number of the vector
+ *
+ * @return
+ *   0 on success, and a negative error on failure.
+ */
+int ivshmem_client_notify(const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer, unsigned vector);
+
+/**
+ * Send a notification to all vectors of a peer
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer
+ *   The peer to be notified
+ *
+ * @return
+ *   0 on success, and a negative error on failure (at least one
+ *   notification failed).
+ */
+int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
+    const struct ivshmem_client_peer *peer);
+
+/**
+ * Broadcat a notification to all vectors of all peers
+ *
+ * @param client
+ *   The ivshmem client
+ *
+ * @return
+ *   0 on success, and a negative error on failure (at least one
+ *   notification failed).
+ */
+int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
+
+/**
+ * Search a peer from its identifier
+ *
+ * Return the peer structure from its peer_id. If the given peer_id is
+ * the local id, the function returns the local peer structure.
+ *
+ * @param client
+ *   The ivshmem client
+ * @param peer_id
+ *   The identifier of the peer structure
+ *
+ * @return
+ *   The peer structure, or NULL if not found
+ */
+struct ivshmem_client_peer *
+ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
+
+/**
+ * Dump information of this ivshmem client on stdout
+ *
+ * Dump the id and the vectors of the given ivshmem client and the list
+ * of its peers and their vectors on stdout.
+ *
+ * @param client
+ *   The ivshmem client
+ */
+void ivshmem_client_dump(const struct ivshmem_client *client);
+
+#endif /* _IVSHMEM_CLIENT_ */
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
new file mode 100644
index 0000000..0d53f55
--- /dev/null
+++ b/contrib/ivshmem-client/main.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include "ivshmem-client.h"
+
+#define DEFAULT_VERBOSE        0
+#define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
+
+struct ivshmem_client_args {
+    int verbose;
+    char *unix_sock_path;
+};
+
+/* show usage and exit with given error code */
+static void
+usage(const char *name, int code)
+{
+    fprintf(stderr, "%s [opts]\n", name);
+    fprintf(stderr, "  -h: show this help\n");
+    fprintf(stderr, "  -v: verbose mode\n");
+    fprintf(stderr, "  -S <unix_sock_path>: path to the unix socket\n"
+                    "     to listen to.\n"
+                    "     default=%s\n", DEFAULT_UNIX_SOCK_PATH);
+    exit(code);
+}
+
+/* parse the program arguments, exit on error */
+static void
+parse_args(struct ivshmem_client_args *args, int argc, char *argv[])
+{
+    char c;
+
+    while ((c = getopt(argc, argv,
+                       "h"  /* help */
+                       "v"  /* verbose */
+                       "S:" /* unix_sock_path */
+                      )) != -1) {
+
+        switch (c) {
+        case 'h': /* help */
+            usage(argv[0], 0);
+            break;
+
+        case 'v': /* verbose */
+            args->verbose = 1;
+            break;
+
+        case 'S': /* unix_sock_path */
+            args->unix_sock_path = strdup(optarg);
+            break;
+
+        default:
+            usage(argv[0], 1);
+            break;
+        }
+    }
+}
+
+/* show command line help */
+static void
+cmdline_help(void)
+{
+    printf("dump: dump peers (including us)\n"
+           "int <peer> <vector>: notify one vector on a peer\n"
+           "int <peer> all: notify all vectors of a peer\n"
+           "int all: notify all vectors of all peers (excepting us)\n");
+}
+
+/* read stdin and handle commands */
+static int
+handle_stdin_command(struct ivshmem_client *client)
+{
+    struct ivshmem_client_peer *peer;
+    char buf[128];
+    char *s, *token;
+    int ret;
+    int peer_id, vector;
+
+    memset(buf, 0, sizeof(buf));
+    ret = read(0, buf, sizeof(buf) - 1);
+    if (ret < 0) {
+        return -1;
+    }
+
+    s = buf;
+    while ((token = strsep(&s, "\n\r;")) != NULL) {
+        if (!strcmp(token, "")) {
+            continue;
+        }
+        if (!strcmp(token, "?")) {
+            cmdline_help();
+        }
+        if (!strcmp(token, "help")) {
+            cmdline_help();
+        } else if (!strcmp(token, "dump")) {
+            ivshmem_client_dump(client);
+        } else if (!strcmp(token, "int all")) {
+            ivshmem_client_notify_broadcast(client);
+        } else if (sscanf(token, "int %d %d", &peer_id, &vector) == 2) {
+            peer = ivshmem_client_search_peer(client, peer_id);
+            if (peer == NULL) {
+                printf("cannot find peer_id = %d\n", peer_id);
+                continue;
+            }
+            ivshmem_client_notify(client, peer, vector);
+        } else if (sscanf(token, "int %d all", &peer_id) == 1) {
+            peer = ivshmem_client_search_peer(client, peer_id);
+            if (peer == NULL) {
+                printf("cannot find peer_id = %d\n", peer_id);
+                continue;
+            }
+            ivshmem_client_notify_all_vects(client, peer);
+        } else {
+            printf("invalid command, type help\n");
+        }
+    }
+
+    printf("cmd> ");
+    fflush(stdout);
+    return 0;
+}
+
+/* listen on stdin (command line), on unix socket (notifications of new
+ * and dead peers), and on eventfd (IRQ request) */
+int
+poll_events(struct ivshmem_client *client)
+{
+    fd_set fds;
+    int ret, maxfd;
+
+    while (1) {
+
+        FD_ZERO(&fds);
+        FD_SET(0, &fds); /* add stdin in fd_set */
+        maxfd = 1;
+
+        ivshmem_client_get_fds(client, &fds, &maxfd);
+
+        ret = select(maxfd, &fds, NULL, NULL, NULL);
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            fprintf(stderr, "select error: %s\n", strerror(errno));
+            break;
+        }
+        if (ret == 0) {
+            continue;
+        }
+
+        if (FD_ISSET(0, &fds) &&
+            handle_stdin_command(client) < 0 && errno != EINTR) {
+            fprintf(stderr, "handle_stdin_command() failed\n");
+            break;
+        }
+
+        if (ivshmem_client_handle_fds(client, &fds, maxfd) < 0) {
+            fprintf(stderr, "ivshmem_client_handle_fds() failed\n");
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/* callback when we receive a notification (just display it) */
+void
+notification_cb(const struct ivshmem_client *client,
+                const struct ivshmem_client_peer *peer, unsigned vect,
+                void *arg)
+{
+    (void)client;
+    (void)arg;
+    printf("receive notification from peer_id=%ld vector=%d\n", peer->id, vect);
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct sigaction sa;
+    struct ivshmem_client client;
+    struct ivshmem_client_args args = {
+        .verbose = DEFAULT_VERBOSE,
+        .unix_sock_path = DEFAULT_UNIX_SOCK_PATH,
+    };
+
+    /* parse arguments, will exit on error */
+    parse_args(&args, argc, argv);
+
+    /* Ignore SIGPIPE, see this link for more info:
+     * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags = 0;
+    if (sigemptyset(&sa.sa_mask) == -1 ||
+        sigaction(SIGPIPE, &sa, 0) == -1) {
+        perror("failed to ignore SIGPIPE; sigaction");
+        return 1;
+    }
+
+    cmdline_help();
+    printf("cmd> ");
+    fflush(stdout);
+
+    if (ivshmem_client_init(&client, args.unix_sock_path, notification_cb,
+                            NULL, args.verbose) < 0) {
+        fprintf(stderr, "cannot init client\n");
+        return 1;
+    }
+
+    while (1) {
+        if (ivshmem_client_connect(&client) < 0) {
+            fprintf(stderr, "cannot connect to server, retry in 1 second\n");
+            sleep(1);
+            continue;
+        }
+
+        fprintf(stdout, "listen on server socket %d\n", client.sock_fd);
+
+        if (poll_events(&client) == 0) {
+            continue;
+        }
+
+        /* disconnected from server, reset all peers */
+        fprintf(stdout, "disconnected from server\n");
+
+        ivshmem_client_close(&client);
+    }
+
+    return 0;
+}
diff --git a/contrib/ivshmem-server/Makefile b/contrib/ivshmem-server/Makefile
new file mode 100644
index 0000000..26b4a72
--- /dev/null
+++ b/contrib/ivshmem-server/Makefile
@@ -0,0 +1,29 @@
+# Copyright 6WIND S.A., 2014
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# (at your option) any later version.  See the COPYING file in the
+# top-level directory.
+
+S ?= $(CURDIR)
+O ?= $(CURDIR)
+
+CFLAGS += -Wall -Wextra -Werror -g
+LDFLAGS +=
+LDLIBS += -lrt
+
+VPATH = $(S)
+PROG = ivshmem-server
+OBJS := $(O)/ivshmem-server.o
+OBJS += $(O)/main.o
+
+$(O)/%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+$(O)/$(PROG): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: all
+all: $(O)/$(PROG)
+
+clean:
+	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
new file mode 100644
index 0000000..f6497bb
--- /dev/null
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <fcntl.h>
+
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/eventfd.h>
+
+#include "ivshmem-server.h"
+
+/* log a message on stdout if verbose=1 */
+#define debug_log(server, fmt, ...) do { \
+        if ((server)->verbose) {         \
+            printf(fmt, ## __VA_ARGS__); \
+        }                                \
+    } while (0)
+
+/* browse the queue, allowing to remove/free the current element */
+#define    TAILQ_FOREACH_SAFE(var, var2, head, field)            \
+    for ((var) = TAILQ_FIRST((head)),                            \
+             (var2) = ((var) ? TAILQ_NEXT((var), field) : NULL); \
+         (var);                                                  \
+         (var) = (var2),                                         \
+             (var2) = ((var2) ? TAILQ_NEXT((var2), field) : NULL))
+
+/** maximum size of a huge page, used by ivshmem_ftruncate() */
+#define MAX_HUGEPAGE_SIZE (1024 * 1024 * 1024)
+
+/** default listen backlog (number of sockets not accepted) */
+#define IVSHMEM_SERVER_LISTEN_BACKLOG 10
+
+/* send message to a client unix socket */
+static int
+send_one_msg(int sock_fd, long peer_id, int fd)
+{
+    int ret;
+    struct msghdr msg;
+    struct iovec iov[1];
+    union {
+        struct cmsghdr cmsg;
+        char control[CMSG_SPACE(sizeof(int))];
+    } msg_control;
+    struct cmsghdr *cmsg;
+
+    iov[0].iov_base = &peer_id;
+    iov[0].iov_len = sizeof(peer_id);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+
+    /* if fd is specified, add it in a cmsg */
+    if (fd >= 0) {
+        msg.msg_control = &msg_control;
+        msg.msg_controllen = sizeof(msg_control);
+        cmsg = CMSG_FIRSTHDR(&msg);
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+        memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+    }
+
+    ret = sendmsg(sock_fd, &msg, 0);
+    if (ret <= 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/* free a peer when the server advertise a disconnection or when the
+ * server is freed */
+static void
+free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
+{
+    unsigned vector;
+    struct ivshmem_server_peer *other_peer;
+
+    debug_log(server, "free peer %ld\n", peer->id);
+    close(peer->sock_fd);
+    TAILQ_REMOVE(&server->peer_list, peer, next);
+
+    /* advertise the deletion to other peers */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        send_one_msg(other_peer->sock_fd, peer->id, -1);
+    }
+
+    for (vector = 0; vector < peer->vectors_count; vector++) {
+        close(peer->vectors[vector]);
+    }
+
+    free(peer);
+}
+
+/* send the peer id and the shm_fd just after a new client connection */
+static int
+send_initial_info(struct ivshmem_server *server,
+                  struct ivshmem_server_peer *peer)
+{
+    int ret;
+
+    /* send the peer id to the client */
+    ret = send_one_msg(peer->sock_fd, peer->id, -1);
+    if (ret < 0) {
+        debug_log(server, "cannot send peer id: %s\n", strerror(errno));
+        return -1;
+    }
+
+    /* send the shm_fd */
+    ret = send_one_msg(peer->sock_fd, -1, server->shm_fd);
+    if (ret < 0) {
+        debug_log(server, "cannot send shm fd: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+/* handle message on listening unix socket (new client connection) */
+static int
+handle_new_conn(struct ivshmem_server *server)
+{
+    struct ivshmem_server_peer *peer, *other_peer;
+    struct sockaddr_un unaddr;
+    socklen_t unaddr_len;
+    int newfd;
+    unsigned i;
+
+    /* accept the incoming connection */
+    unaddr_len = sizeof(unaddr);
+    newfd = accept(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len);
+    if (newfd < 0) {
+        debug_log(server, "cannot accept() %s\n", strerror(errno));
+        return -1;
+    }
+
+    debug_log(server, "accept()=%d\n", newfd);
+
+    /* allocate new structure for this peer */
+    peer = malloc(sizeof(*peer));
+    if (peer == NULL) {
+        debug_log(server, "cannot allocate new peer\n");
+        close(newfd);
+        return -1;
+    }
+
+    /* initialize the peer struct, one eventfd per vector */
+    memset(peer, 0, sizeof(*peer));
+    peer->sock_fd = newfd;
+
+    /* get an unused peer id */
+    while (ivshmem_server_search_peer(server, server->cur_id) != NULL) {
+        server->cur_id++;
+    }
+    peer->id = server->cur_id++;
+
+    /* create eventfd, one per vector */
+    peer->vectors_count = server->n_vectors;
+    for (i = 0; i < peer->vectors_count; i++) {
+        peer->vectors[i] = eventfd(0, 0);
+        if (peer->vectors[i] < 0) {
+            debug_log(server, "cannot create eventfd\n");
+            goto fail;
+        }
+    }
+
+    /* send peer id and shm fd */
+    if (send_initial_info(server, peer) < 0) {
+        debug_log(server, "cannot send initial info\n");
+        goto fail;
+    }
+
+    /* advertise the new peer to others */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        for (i = 0; i < peer->vectors_count; i++) {
+            send_one_msg(other_peer->sock_fd, peer->id, peer->vectors[i]);
+        }
+    }
+
+    /* advertise the other peers to the new one */
+    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+        for (i = 0; i < peer->vectors_count; i++) {
+            send_one_msg(peer->sock_fd, other_peer->id, other_peer->vectors[i]);
+        }
+    }
+
+    /* advertise the new peer to itself */
+    for (i = 0; i < peer->vectors_count; i++) {
+        send_one_msg(peer->sock_fd, peer->id, peer->vectors[i]);
+    }
+
+    TAILQ_INSERT_TAIL(&server->peer_list, peer, next);
+    debug_log(server, "new peer id = %ld\n", peer->id);
+    return 0;
+
+fail:
+    while (i--) {
+        close(peer->vectors[i]);
+    }
+    peer->sock_fd = -1;
+    close(newfd);
+    return -1;
+}
+
+/* Try to ftruncate a file to next power of 2 of shmsize.
+ * If it fails; all power of 2 above shmsize are tested until
+ * we reach the maximum huge page size. This is useful
+ * if the shm file is in a hugetlbfs that cannot be truncated to the
+ * shm_size value. */
+static int
+ivshmem_ftruncate(int fd, unsigned shmsize)
+{
+    int ret;
+
+    /* align shmsize to next power of 2 */
+    shmsize--;
+    shmsize |= shmsize >> 1;
+    shmsize |= shmsize >> 2;
+    shmsize |= shmsize >> 4;
+    shmsize |= shmsize >> 8;
+    shmsize |= shmsize >> 16;
+    shmsize++;
+
+    while (shmsize <= MAX_HUGEPAGE_SIZE) {
+        ret = ftruncate(fd, shmsize);
+        if (ret == 0) {
+            return ret;
+        }
+        shmsize *= 2;
+    }
+
+    return -1;
+}
+
+/* Init a new ivshmem server */
+int
+ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
+                    const char *shm_path, size_t shm_size, unsigned n_vectors,
+                    int verbose)
+{
+    memset(server, 0, sizeof(*server));
+
+    snprintf(server->unix_sock_path, sizeof(server->unix_sock_path),
+             "%s", unix_sock_path);
+    snprintf(server->shm_path, sizeof(server->shm_path),
+             "%s", shm_path);
+
+    server->shm_size = shm_size;
+    server->n_vectors = n_vectors;
+    server->verbose = verbose;
+
+    TAILQ_INIT(&server->peer_list);
+
+    return 0;
+}
+
+/* open shm, create and bind to the unix socket */
+int
+ivshmem_server_start(struct ivshmem_server *server)
+{
+    struct sockaddr_un sun;
+    int shm_fd, sock_fd;
+
+    /* open shm file */
+    shm_fd = shm_open(server->shm_path, O_CREAT|O_RDWR, S_IRWXU);
+    if (shm_fd < 0) {
+        fprintf(stderr, "cannot open shm file %s: %s\n", server->shm_path,
+                strerror(errno));
+        return -1;
+    }
+    if (ivshmem_ftruncate(shm_fd, server->shm_size) < 0) {
+        fprintf(stderr, "ftruncate(%s) failed: %s\n", server->shm_path,
+                strerror(errno));
+        return -1;
+    }
+
+    debug_log(server, "create & bind socket %s\n", server->unix_sock_path);
+
+    /* create the unix listening socket */
+    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock_fd < 0) {
+        debug_log(server, "cannot create socket: %s\n", strerror(errno));
+        close(shm_fd);
+        return -1;
+    }
+
+    sun.sun_family = AF_UNIX;
+    snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", server->unix_sock_path);
+    unlink(sun.sun_path);
+    if (bind(sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
+        debug_log(server, "cannot connect to %s: %s\n", sun.sun_path,
+                  strerror(errno));
+        close(sock_fd);
+        close(shm_fd);
+        return -1;
+    }
+
+    if (listen(sock_fd, IVSHMEM_SERVER_LISTEN_BACKLOG) < 0) {
+        debug_log(server, "listen() failed: %s\n", strerror(errno));
+        close(sock_fd);
+        close(shm_fd);
+        return -1;
+    }
+
+    server->sock_fd = sock_fd;
+    server->shm_fd = shm_fd;
+
+    return 0;
+}
+
+/* close connections to clients, the unix socket and the shm fd */
+void
+ivshmem_server_close(struct ivshmem_server *server)
+{
+    struct ivshmem_server_peer *peer;
+
+    debug_log(server, "close server\n");
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        free_peer(server, peer);
+    }
+
+    close(server->sock_fd);
+    close(server->shm_fd);
+    server->sock_fd = -1;
+    server->shm_fd = -1;
+}
+
+/* get the fd_set according to the unix socket and the peer list */
+void
+ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
+                       int *maxfd)
+{
+    struct ivshmem_server_peer *peer;
+
+    FD_SET(server->sock_fd, fds);
+    if (server->sock_fd >= *maxfd) {
+        *maxfd = server->sock_fd + 1;
+    }
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        FD_SET(peer->sock_fd, fds);
+        if (peer->sock_fd >= *maxfd) {
+            *maxfd = peer->sock_fd + 1;
+        }
+    }
+}
+
+/* process incoming messages on the sockets in fd_set */
+int
+ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
+{
+    struct ivshmem_server_peer *peer, *peer_next;
+
+    if (server->sock_fd < maxfd && FD_ISSET(server->sock_fd, fds) &&
+        handle_new_conn(server) < 0 && errno != EINTR) {
+        debug_log(server, "handle_new_conn() failed\n");
+        return -1;
+    }
+
+    TAILQ_FOREACH_SAFE(peer, peer_next, &server->peer_list, next) {
+        /* any message from a peer socket result in a close() */
+        debug_log(server, "peer->sock_fd=%d\n", peer->sock_fd);
+        if (peer->sock_fd < maxfd && FD_ISSET(peer->sock_fd, fds)) {
+            free_peer(server, peer);
+        }
+    }
+
+    return 0;
+}
+
+/* lookup peer from its id */
+struct ivshmem_server_peer *
+ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
+{
+    struct ivshmem_server_peer *peer;
+
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        if (peer->id == peer_id) {
+            return peer;
+        }
+    }
+    return NULL;
+}
+
+/* dump our info, the list of peers their vectors on stdout */
+void
+ivshmem_server_dump(const struct ivshmem_server *server)
+{
+    const struct ivshmem_server_peer *peer;
+    unsigned vector;
+
+    /* dump peers */
+    TAILQ_FOREACH(peer, &server->peer_list, next) {
+        printf("peer_id = %ld\n", peer->id);
+
+        for (vector = 0; vector < peer->vectors_count; vector++) {
+            printf("  vector %d is enabled (fd=%d)\n", vector,
+                   peer->vectors[vector]);
+        }
+    }
+}
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
new file mode 100644
index 0000000..cd74bbf
--- /dev/null
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_SERVER_
+#define _IVSHMEM_SERVER_
+
+/**
+ * The ivshmem server is a daemon that creates a unix socket in listen
+ * mode. The ivshmem clients (qemu or ivshmem-client) connect to this
+ * unix socket. For each client, the server will create some eventfd
+ * (see EVENTFD(2)), one per vector. These fd are transmitted to all
+ * clients using the SCM_RIGHTS cmsg message. Therefore, each client is
+ * able to send a notification to another client without beeing
+ * "profixied" by the server.
+ *
+ * We use this mechanism to send interruptions between guests.
+ * qemu is able to transform an event on a eventfd into a PCI MSI-x
+ * interruption in the guest.
+ *
+ * The ivshmem server is also able to share the file descriptor
+ * associated to the ivshmem shared memory.
+ */
+
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+
+/**
+ * Maximum number of notification vectors supported by the server
+ */
+#define IVSHMEM_SERVER_MAX_VECTORS 64
+
+/**
+ * Structure storing a peer
+ *
+ * Each time a client connects to an ivshmem server, a new
+ * ivshmem_server_peer structure is created. This peer and all its
+ * vectors are advertised to all connected clients through the connected
+ * unix sockets.
+ */
+struct ivshmem_server_peer {
+    TAILQ_ENTRY(ivshmem_server_peer) next;    /**< next in list*/
+    int sock_fd;                                /**< connected unix sock */
+    long id;                                    /**< the id of the peer */
+    int vectors[IVSHMEM_SERVER_MAX_VECTORS];  /**< one fd per vector */
+    unsigned vectors_count;                     /**< number of vectors */
+};
+TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
+
+/**
+ * Structure describing an ivshmem server
+ *
+ * This structure stores all information related to our server: the name
+ * of the server unix socket and the list of connected peers.
+ */
+struct ivshmem_server {
+    char unix_sock_path[PATH_MAX];  /**< path to unix socket */
+    int sock_fd;                    /**< unix sock file descriptor */
+    char shm_path[PATH_MAX];        /**< path to shm */
+    size_t shm_size;                /**< size of shm */
+    int shm_fd;                     /**< shm file descriptor */
+    unsigned n_vectors;             /**< number of vectors */
+    long cur_id;                    /**< id to be given to next client */
+    int verbose;                    /**< true in verbose mode */
+    struct ivshmem_server_peer_list peer_list;  /**< list of peers */
+};
+
+/**
+ * Initialize an ivshmem server
+ *
+ * @param server
+ *   A pointer to an uninitialized ivshmem_server structure
+ * @param unix_sock_path
+ *   The pointer to the unix socket file name
+ * @param shm_path
+ *   Path to the shared memory. The path corresponds to a POSIX shm name.
+ *   To use a real file, for instance in a hugetlbfs, it is possible to
+ *   use /../../abspath/to/file.
+ * @param shm_size
+ *   Size of shared memory
+ * @param n_vectors
+ *   Number of interrupt vectors per client
+ * @param verbose
+ *   True to enable verbose mode
+ *
+ * @return
+ *   0 on success, negative value on error
+ */
+int
+ivshmem_server_init(struct ivshmem_server *server,
+    const char *unix_sock_path, const char *shm_path, size_t shm_size,
+    unsigned n_vectors, int verbose);
+
+/**
+ * Open the shm, then create and bind to the unix socket
+ *
+ * @param server
+ *   The pointer to the initialized ivshmem server structure
+ *
+ * @return
+ *   0 on success, or a negative value on error
+ */
+int ivshmem_server_start(struct ivshmem_server *server);
+
+/**
+ * Close the server
+ *
+ * Close connections to all clients, close the unix socket and the
+ * shared memory file descriptor. The structure remains initialized, so
+ * it is possible to call ivshmem_server_start() again after a call to
+ * ivshmem_server_close().
+ *
+ * @param server
+ *   The ivshmem server
+ */
+void ivshmem_server_close(struct ivshmem_server *server);
+
+/**
+ * Fill a fd_set with file descriptors to be monitored
+ *
+ * This function will fill a fd_set with all file descriptors that must
+ * be polled (unix server socket and peers unix socket). The function
+ * will not initialize the fd_set, it is up to the caller to do it.
+ *
+ * @param server
+ *   The ivshmem server
+ * @param fds
+ *   The fd_set to be updated
+ * @param maxfd
+ *   Must be set to the max file descriptor + 1 in fd_set. This value is
+ *   updated if this function adds a greated fd in fd_set.
+ */
+void
+ivshmem_server_get_fds(const struct ivshmem_server *server,
+    fd_set *fds, int *maxfd);
+
+/**
+ * Read and handle new messages
+ *
+ * Given a fd_set (for instance filled by a call to select()), handle
+ * incoming messages from peers.
+ *
+ * @param server
+ *   The ivshmem server
+ * @param fds
+ *   The fd_set containing the file descriptors to be checked. Note
+ *   that file descriptors that are not related to our server are
+ *   ignored.
+ * @param maxfd
+ *   The maximum fd in fd_set, plus one.
+ *
+ * @return
+ *   0 on success, negative value on failure.
+ */
+int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
+    int maxfd);
+
+/**
+ * Search a peer from its identifier
+ *
+ * @param server
+ *   The ivshmem server
+ * @param peer_id
+ *   The identifier of the peer structure
+ *
+ * @return
+ *   The peer structure, or NULL if not found
+ */
+struct ivshmem_server_peer *
+ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
+
+/**
+ * Dump information of this ivshmem server and its peers on stdout
+ *
+ * @param server
+ *   The ivshmem server
+ */
+void ivshmem_server_dump(const struct ivshmem_server *server);
+
+#endif /* _IVSHMEM_SERVER_ */
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
new file mode 100644
index 0000000..36b7028
--- /dev/null
+++ b/contrib/ivshmem-server/main.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <getopt.h>
+
+#include "ivshmem-server.h"
+
+#define DEFAULT_VERBOSE        0
+#define DEFAULT_FOREGROUND     0
+#define DEFAULT_PID_FILE       "/var/run/ivshmem-server.pid"
+#define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
+#define DEFAULT_SHM_PATH       "ivshmem"
+#define DEFAULT_SHM_SIZE       (1024*1024)
+#define DEFAULT_N_VECTORS      16
+
+/* arguments given by the user */
+struct ivshmem_server_args {
+    int verbose;
+    int foreground;
+    char *pid_file;
+    char *unix_socket_path;
+    char *shm_path;
+    size_t shm_size;
+    unsigned n_vectors;
+};
+
+/* show usage and exit with given error code */
+static void
+usage(const char *name, int code)
+{
+    fprintf(stderr, "%s [opts]\n", name);
+    fprintf(stderr, "  -h: show this help\n");
+    fprintf(stderr, "  -v: verbose mode\n");
+    fprintf(stderr, "  -F: foreground mode (default is to daemonize)\n");
+    fprintf(stderr, "  -p <pid_file>: path to the PID file (used in daemon\n"
+                    "     mode only).\n"
+                    "     Default=%s\n", DEFAULT_SHM_PATH);
+    fprintf(stderr, "  -S <unix_socket_path>: path to the unix socket\n"
+                    "     to listen to.\n"
+                    "     Default=%s\n", DEFAULT_UNIX_SOCK_PATH);
+    fprintf(stderr, "  -m <shm_path>: path to the shared memory.\n"
+                    "     The path corresponds to a POSIX shm name. To use a\n"
+                    "     real file, for instance in a hugetlbfs, use\n"
+                    "     /../../abspath/to/file.\n"
+                    "     default=%s\n", DEFAULT_SHM_PATH);
+    fprintf(stderr, "  -l <size>: size of shared memory in bytes. The suffix\n"
+                    "     K, M and G can be used (ex: 1K means 1024).\n"
+                    "     default=%u\n", DEFAULT_SHM_SIZE);
+    fprintf(stderr, "  -n <n_vects>: number of vectors.\n"
+                    "     default=%u\n", DEFAULT_N_VECTORS);
+
+    exit(code);
+}
+
+/* parse the size of shm */
+static int
+parse_size(const char *val_str, size_t *val)
+{
+    char *endptr;
+    unsigned long long tmp;
+
+    errno = 0;
+    tmp = strtoull(val_str, &endptr, 0);
+    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
+        return -1;
+    }
+    if (endptr == val_str) {
+        return -1;
+    }
+    if (endptr[0] == 'K' && endptr[1] == '\0') {
+        tmp *= 1024;
+    } else if (endptr[0] == 'M' && endptr[1] == '\0') {
+        tmp *= 1024 * 1024;
+    } else if (endptr[0] == 'G' && endptr[1] == '\0') {
+        tmp *= 1024 * 1024 * 1024;
+    } else if (endptr[0] != '\0') {
+        return -1;
+    }
+
+    *val = tmp;
+    return 0;
+}
+
+/* parse an unsigned int */
+static int
+parse_uint(const char *val_str, unsigned *val)
+{
+    char *endptr;
+    unsigned long tmp;
+
+    errno = 0;
+    tmp = strtoul(val_str, &endptr, 0);
+    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
+        return -1;
+    }
+    if (endptr == val_str || endptr[0] != '\0') {
+        return -1;
+    }
+    *val = tmp;
+    return 0;
+}
+
+/* parse the program arguments, exit on error */
+static void
+parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
+{
+    char c;
+
+    while ((c = getopt(argc, argv,
+                       "h"  /* help */
+                       "v"  /* verbose */
+                       "F"  /* foreground */
+                       "p:" /* pid_file */
+                       "S:" /* unix_socket_path */
+                       "m:" /* shm_path */
+                       "l:" /* shm_size */
+                       "n:" /* n_vectors */
+                      )) != -1) {
+
+        switch (c) {
+        case 'h': /* help */
+            usage(argv[0], 0);
+            break;
+
+        case 'v': /* verbose */
+            args->verbose = 1;
+            break;
+
+        case 'F': /* foreground */
+            args->foreground = 1;
+            break;
+
+        case 'p': /* pid_file */
+            args->pid_file = strdup(optarg);
+            break;
+
+        case 'S': /* unix_socket_path */
+            args->unix_socket_path = strdup(optarg);
+            break;
+
+        case 'm': /* shm_path */
+            args->shm_path = strdup(optarg);
+            break;
+
+        case 'l': /* shm_size */
+            if (parse_size(optarg, &args->shm_size) < 0) {
+                fprintf(stderr, "cannot parse shm size\n");
+                usage(argv[0], 1);
+            }
+            break;
+
+        case 'n': /* n_vectors */
+            if (parse_uint(optarg, &args->n_vectors) < 0) {
+                fprintf(stderr, "cannot parse n_vectors\n");
+                usage(argv[0], 1);
+            }
+            break;
+
+        default:
+            usage(argv[0], 1);
+            break;
+        }
+    }
+
+    if (args->n_vectors > IVSHMEM_SERVER_MAX_VECTORS) {
+        fprintf(stderr, "too many requested vectors (max is %d)\n",
+                IVSHMEM_SERVER_MAX_VECTORS);
+        usage(argv[0], 1);
+    }
+
+    if (args->verbose == 1 && args->foreground == 0) {
+        fprintf(stderr, "cannot use verbose in daemon mode\n");
+        usage(argv[0], 1);
+    }
+}
+
+/* wait for events on listening server unix socket and connected client
+ * sockets */
+int
+poll_events(struct ivshmem_server *server)
+{
+    fd_set fds;
+    int ret, maxfd;
+
+    while (1) {
+
+        FD_ZERO(&fds);
+        maxfd = 0;
+        ivshmem_server_get_fds(server, &fds, &maxfd);
+
+        ret = select(maxfd, &fds, NULL, NULL, NULL);
+
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            fprintf(stderr, "select error: %s\n", strerror(errno));
+            break;
+        }
+        if (ret == 0) {
+            continue;
+        }
+
+        if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
+            fprintf(stderr, "ivshmem_server_handle_fds() failed\n");
+            break;
+        }
+    }
+
+    return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+    struct ivshmem_server server;
+    struct sigaction sa;
+    struct ivshmem_server_args args = {
+        .verbose = DEFAULT_VERBOSE,
+        .foreground = DEFAULT_FOREGROUND,
+        .pid_file = DEFAULT_PID_FILE,
+        .unix_socket_path = DEFAULT_UNIX_SOCK_PATH,
+        .shm_path = DEFAULT_SHM_PATH,
+        .shm_size = DEFAULT_SHM_SIZE,
+        .n_vectors = DEFAULT_N_VECTORS,
+    };
+
+    /* parse arguments, will exit on error */
+    parse_args(&args, argc, argv);
+
+    /* Ignore SIGPIPE, see this link for more info:
+     * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
+    sa.sa_handler = SIG_IGN;
+    sa.sa_flags = 0;
+    if (sigemptyset(&sa.sa_mask) == -1 ||
+        sigaction(SIGPIPE, &sa, 0) == -1) {
+        perror("failed to ignore SIGPIPE; sigaction");
+        return 1;
+    }
+
+    /* init the ivshms structure */
+    if (ivshmem_server_init(&server, args.unix_socket_path, args.shm_path,
+                            args.shm_size, args.n_vectors, args.verbose) < 0) {
+        fprintf(stderr, "cannot init server\n");
+        return 1;
+    }
+
+    /* start the ivshmem server (open shm & unix socket) */
+    if (ivshmem_server_start(&server) < 0) {
+        fprintf(stderr, "cannot bind\n");
+        return 1;
+    }
+
+    /* daemonize if asked to */
+    if (!args.foreground) {
+        FILE *fp;
+
+        if (daemon(1, 1) < 0) {
+            fprintf(stderr, "cannot daemonize: %s\n", strerror(errno));
+            return 1;
+        }
+
+        /* write pid file */
+        fp = fopen(args.pid_file, "w");
+        if (fp == NULL) {
+            fprintf(stderr, "cannot write pid file: %s\n", strerror(errno));
+            return 1;
+        }
+
+        fprintf(fp, "%d\n", (int) getpid());
+        fclose(fp);
+    }
+
+    poll_events(&server);
+
+    fprintf(stdout, "server disconnected\n");
+    ivshmem_server_close(&server);
+
+    return 0;
+}
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 2b232ae..380d573 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -1250,9 +1250,13 @@ is qemu.git/contrib/ivshmem-server.  An example syntax when using the shared
 memory server is:
 
 @example
-qemu-system-i386 -device ivshmem,size=<size in format accepted by -m>[,chardev=<id>]
-                 [,msi=on][,ioeventfd=on][,vectors=n][,role=peer|master]
-qemu-system-i386 -chardev socket,path=<path>,id=<id>
+# First start the ivshmem server once and for all
+ivshmem-server -p <pidfile> -S <path> -m <shm name> -l <shm size> -n <vectors n>
+
+# Then start your qemu instances with matching arguments
+qemu-system-i386 -device ivshmem,size=<shm size>,vectors=<vectors n>,chardev=<id>
+                 [,msi=on][,ioeventfd=on][,role=peer|master]
+                 -chardev socket,path=<path>,id=<id>
 @end example
 
 When using the server, the guest will be assigned a VM ID (>=0) that allows guests
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 02/14] docs: update ivshmem device spec
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Add some notes on the parts needed to use ivshmem devices: more specifically,
explain the purpose of an ivshmem server and the basic concept to use the
ivshmem devices in guests.
Move some parts of the documentation and re-organise it.

Signed-off-by: David Marchand <david.marchand@6wind.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
---
 docs/specs/ivshmem_device_spec.txt |  124 +++++++++++++++++++++++++++---------
 1 file changed, 93 insertions(+), 31 deletions(-)

diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt
index 667a862..f5f2b95 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -2,30 +2,103 @@
 Device Specification for Inter-VM shared memory device
 ------------------------------------------------------
 
-The Inter-VM shared memory device is designed to share a region of memory to
-userspace in multiple virtual guests.  The memory region does not belong to any
-guest, but is a POSIX memory object on the host.  Optionally, the device may
-support sending interrupts to other guests sharing the same memory region.
+The Inter-VM shared memory device is designed to share a memory region (created
+on the host via the POSIX shared memory API) between multiple QEMU processes
+running different guests. In order for all guests to be able to pick up the
+shared memory area, it is modeled by QEMU as a PCI device exposing said memory
+to the guest as a PCI BAR.
+The memory region does not belong to any guest, but is a POSIX memory object on
+the host. The host can access this shared memory if needed.
+
+The device also provides an optional communication mechanism between guests
+sharing the same memory object. More details about that in the section 'Guest to
+guest communication' section.
 
 
 The Inter-VM PCI device
 -----------------------
 
-*BARs*
+From the VM point of view, the ivshmem PCI device supports three BARs.
+
+- BAR0 is a 1 Kbyte MMIO region to support registers and interrupts when MSI is
+  not used.
+- BAR1 is used for MSI-X when it is enabled in the device.
+- BAR2 is used to access the shared memory object.
+
+It is your choice how to use the device but you must choose between two
+behaviors :
+
+- basically, if you only need the shared memory part, you will map BAR2.
+  This way, you have access to the shared memory in guest and can use it as you
+  see fit (memnic, for example, uses it in userland
+  http://dpdk.org/browse/memnic).
+
+- BAR0 and BAR1 are used to implement an optional communication mechanism
+  through interrupts in the guests. If you need an event mechanism between the
+  guests accessing the shared memory, you will most likely want to write a
+  kernel driver that will handle interrupts. See details in the section 'Guest
+  to guest communication' section.
+
+The behavior is chosen when starting your QEMU processes:
+- no communication mechanism needed, the first QEMU to start creates the shared
+  memory on the host, subsequent QEMU processes will use it.
+
+- communication mechanism needed, an ivshmem server must be started before any
+  QEMU processes, then each QEMU process connects to the server unix socket.
+
+For more details on the QEMU ivshmem parameters, see qemu-doc documentation.
+
+
+Guest to guest communication
+----------------------------
+
+This section details the communication mechanism between the guests accessing
+the ivhsmem shared memory.
 
-The device supports three BARs.  BAR0 is a 1 Kbyte MMIO region to support
-registers.  BAR1 is used for MSI-X when it is enabled in the device.  BAR2 is
-used to map the shared memory object from the host.  The size of BAR2 is
-specified when the guest is started and must be a power of 2 in size.
+*ivshmem server*
 
-*Registers*
+This server code is available in qemu.git/contrib/ivshmem-server.
 
-The device currently supports 4 registers of 32-bits each.  Registers
-are used for synchronization between guests sharing the same memory object when
-interrupts are supported (this requires using the shared memory server).
+The server must be started on the host before any guest.
+It creates a shared memory object then waits for clients to connect on an unix
+socket.
 
-The server assigns each VM an ID number and sends this ID number to the QEMU
-process when the guest starts.
+For each client (QEMU processes) that connects to the server:
+- the server assigns an ID for this client and sends this ID to him as the first
+  message,
+- the server sends a fd to the shared memory object to this client,
+- the server creates a new set of host eventfds associated to the new client and
+  sends this set to all already connected clients,
+- finally, the server sends all the eventfds sets for all clients to the new
+  client.
+
+The server signals all clients when one of them disconnects.
+
+The client IDs are limited to 16 bits because of the current implementation (see
+Doorbell register in 'PCI device registers' subsection). Hence on 65536 clients
+are supported.
+
+All the file descriptors (fd to the shared memory, eventfds for each client)
+are passed to clients using SCM_RIGHTS over the server unix socket.
+
+Apart from the current ivshmem implementation in QEMU, an ivshmem client has
+been provided in qemu.git/contrib/ivshmem-client for debug.
+
+*QEMU as an ivshmem client*
+
+At initialisation, when creating the ivshmem device, QEMU gets its ID from the
+server then make it available through BAR0 IVPosition register for the VM to use
+(see 'PCI device registers' subsection).
+QEMU then uses the fd to the shared memory to map it to BAR2.
+eventfds for all other clients received from the server are stored to implement
+BAR0 Doorbell register (see 'PCI device registers' subsection).
+Finally, eventfds assigned to this QEMU process are used to send interrupts in
+this VM.
+
+*PCI device registers*
+
+From the VM point of view, the ivshmem PCI device supports 4 registers of
+32-bits each.
 
 enum ivshmem_registers {
     IntrMask = 0,
@@ -49,8 +122,8 @@ bit to 0 and unmasked by setting the first bit to 1.
 IVPosition Register: The IVPosition register is read-only and reports the
 guest's ID number.  The guest IDs are non-negative integers.  When using the
 server, since the server is a separate process, the VM ID will only be set when
-the device is ready (shared memory is received from the server and accessible via
-the device).  If the device is not ready, the IVPosition will return -1.
+the device is ready (shared memory is received from the server and accessible
+via the device).  If the device is not ready, the IVPosition will return -1.
 Applications should ensure that they have a valid VM ID before accessing the
 shared memory.
 
@@ -59,8 +132,8 @@ Doorbell register.  The doorbell register is 32-bits, logically divided into
 two 16-bit fields.  The high 16-bits are the guest ID to interrupt and the low
 16-bits are the interrupt vector to trigger.  The semantics of the value
 written to the doorbell depends on whether the device is using MSI or a regular
-pin-based interrupt.  In short, MSI uses vectors while regular interrupts set the
-status register.
+pin-based interrupt.  In short, MSI uses vectors while regular interrupts set
+the status register.
 
 Regular Interrupts
 
@@ -71,7 +144,7 @@ interrupt in the destination guest.
 
 Message Signalled Interrupts
 
-A ivshmem device may support multiple MSI vectors.  If so, the lower 16-bits
+An ivshmem device may support multiple MSI vectors.  If so, the lower 16-bits
 written to the Doorbell register must be between 0 and the maximum number of
 vectors the guest supports.  The lower 16 bits written to the doorbell is the
 MSI vector that will be raised in the destination guest.  The number of MSI
@@ -83,14 +156,3 @@ interrupt itself should be communicated via the shared memory region.  Devices
 supporting multiple MSI vectors can use different vectors to indicate different
 events have occurred.  The semantics of interrupt vectors are left to the
 user's discretion.
-
-
-Usage in the Guest
-------------------
-
-The shared memory device is intended to be used with the provided UIO driver.
-Very little configuration is needed.  The guest should map BAR0 to access the
-registers (an array of 32-bit ints allows simple writing) and map BAR2 to
-access the shared memory region itself.  The size of the shared memory region
-is specified when the guest (or shared memory server) is started.  A guest may
-map the whole shared memory region or only part of it.
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 02/14] docs: update ivshmem device spec
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Add some notes on the parts needed to use ivshmem devices: more specifically,
explain the purpose of an ivshmem server and the basic concept to use the
ivshmem devices in guests.
Move some parts of the documentation and re-organise it.

Signed-off-by: David Marchand <david.marchand@6wind.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
---
 docs/specs/ivshmem_device_spec.txt |  124 +++++++++++++++++++++++++++---------
 1 file changed, 93 insertions(+), 31 deletions(-)

diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt
index 667a862..f5f2b95 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -2,30 +2,103 @@
 Device Specification for Inter-VM shared memory device
 ------------------------------------------------------
 
-The Inter-VM shared memory device is designed to share a region of memory to
-userspace in multiple virtual guests.  The memory region does not belong to any
-guest, but is a POSIX memory object on the host.  Optionally, the device may
-support sending interrupts to other guests sharing the same memory region.
+The Inter-VM shared memory device is designed to share a memory region (created
+on the host via the POSIX shared memory API) between multiple QEMU processes
+running different guests. In order for all guests to be able to pick up the
+shared memory area, it is modeled by QEMU as a PCI device exposing said memory
+to the guest as a PCI BAR.
+The memory region does not belong to any guest, but is a POSIX memory object on
+the host. The host can access this shared memory if needed.
+
+The device also provides an optional communication mechanism between guests
+sharing the same memory object. More details about that in the section 'Guest to
+guest communication' section.
 
 
 The Inter-VM PCI device
 -----------------------
 
-*BARs*
+From the VM point of view, the ivshmem PCI device supports three BARs.
+
+- BAR0 is a 1 Kbyte MMIO region to support registers and interrupts when MSI is
+  not used.
+- BAR1 is used for MSI-X when it is enabled in the device.
+- BAR2 is used to access the shared memory object.
+
+It is your choice how to use the device but you must choose between two
+behaviors :
+
+- basically, if you only need the shared memory part, you will map BAR2.
+  This way, you have access to the shared memory in guest and can use it as you
+  see fit (memnic, for example, uses it in userland
+  http://dpdk.org/browse/memnic).
+
+- BAR0 and BAR1 are used to implement an optional communication mechanism
+  through interrupts in the guests. If you need an event mechanism between the
+  guests accessing the shared memory, you will most likely want to write a
+  kernel driver that will handle interrupts. See details in the section 'Guest
+  to guest communication' section.
+
+The behavior is chosen when starting your QEMU processes:
+- no communication mechanism needed, the first QEMU to start creates the shared
+  memory on the host, subsequent QEMU processes will use it.
+
+- communication mechanism needed, an ivshmem server must be started before any
+  QEMU processes, then each QEMU process connects to the server unix socket.
+
+For more details on the QEMU ivshmem parameters, see qemu-doc documentation.
+
+
+Guest to guest communication
+----------------------------
+
+This section details the communication mechanism between the guests accessing
+the ivhsmem shared memory.
 
-The device supports three BARs.  BAR0 is a 1 Kbyte MMIO region to support
-registers.  BAR1 is used for MSI-X when it is enabled in the device.  BAR2 is
-used to map the shared memory object from the host.  The size of BAR2 is
-specified when the guest is started and must be a power of 2 in size.
+*ivshmem server*
 
-*Registers*
+This server code is available in qemu.git/contrib/ivshmem-server.
 
-The device currently supports 4 registers of 32-bits each.  Registers
-are used for synchronization between guests sharing the same memory object when
-interrupts are supported (this requires using the shared memory server).
+The server must be started on the host before any guest.
+It creates a shared memory object then waits for clients to connect on an unix
+socket.
 
-The server assigns each VM an ID number and sends this ID number to the QEMU
-process when the guest starts.
+For each client (QEMU processes) that connects to the server:
+- the server assigns an ID for this client and sends this ID to him as the first
+  message,
+- the server sends a fd to the shared memory object to this client,
+- the server creates a new set of host eventfds associated to the new client and
+  sends this set to all already connected clients,
+- finally, the server sends all the eventfds sets for all clients to the new
+  client.
+
+The server signals all clients when one of them disconnects.
+
+The client IDs are limited to 16 bits because of the current implementation (see
+Doorbell register in 'PCI device registers' subsection). Hence on 65536 clients
+are supported.
+
+All the file descriptors (fd to the shared memory, eventfds for each client)
+are passed to clients using SCM_RIGHTS over the server unix socket.
+
+Apart from the current ivshmem implementation in QEMU, an ivshmem client has
+been provided in qemu.git/contrib/ivshmem-client for debug.
+
+*QEMU as an ivshmem client*
+
+At initialisation, when creating the ivshmem device, QEMU gets its ID from the
+server then make it available through BAR0 IVPosition register for the VM to use
+(see 'PCI device registers' subsection).
+QEMU then uses the fd to the shared memory to map it to BAR2.
+eventfds for all other clients received from the server are stored to implement
+BAR0 Doorbell register (see 'PCI device registers' subsection).
+Finally, eventfds assigned to this QEMU process are used to send interrupts in
+this VM.
+
+*PCI device registers*
+
+From the VM point of view, the ivshmem PCI device supports 4 registers of
+32-bits each.
 
 enum ivshmem_registers {
     IntrMask = 0,
@@ -49,8 +122,8 @@ bit to 0 and unmasked by setting the first bit to 1.
 IVPosition Register: The IVPosition register is read-only and reports the
 guest's ID number.  The guest IDs are non-negative integers.  When using the
 server, since the server is a separate process, the VM ID will only be set when
-the device is ready (shared memory is received from the server and accessible via
-the device).  If the device is not ready, the IVPosition will return -1.
+the device is ready (shared memory is received from the server and accessible
+via the device).  If the device is not ready, the IVPosition will return -1.
 Applications should ensure that they have a valid VM ID before accessing the
 shared memory.
 
@@ -59,8 +132,8 @@ Doorbell register.  The doorbell register is 32-bits, logically divided into
 two 16-bit fields.  The high 16-bits are the guest ID to interrupt and the low
 16-bits are the interrupt vector to trigger.  The semantics of the value
 written to the doorbell depends on whether the device is using MSI or a regular
-pin-based interrupt.  In short, MSI uses vectors while regular interrupts set the
-status register.
+pin-based interrupt.  In short, MSI uses vectors while regular interrupts set
+the status register.
 
 Regular Interrupts
 
@@ -71,7 +144,7 @@ interrupt in the destination guest.
 
 Message Signalled Interrupts
 
-A ivshmem device may support multiple MSI vectors.  If so, the lower 16-bits
+An ivshmem device may support multiple MSI vectors.  If so, the lower 16-bits
 written to the Doorbell register must be between 0 and the maximum number of
 vectors the guest supports.  The lower 16 bits written to the doorbell is the
 MSI vector that will be raised in the destination guest.  The number of MSI
@@ -83,14 +156,3 @@ interrupt itself should be communicated via the shared memory region.  Devices
 supporting multiple MSI vectors can use different vectors to indicate different
 events have occurred.  The semantics of interrupt vectors are left to the
 user's discretion.
-
-
-Usage in the Guest
-------------------
-
-The shared memory device is intended to be used with the provided UIO driver.
-Very little configuration is needed.  The guest should map BAR0 to access the
-registers (an array of 32-bit ints allows simple writing) and map BAR2 to
-access the shared memory region itself.  The size of the shared memory region
-is specified when the guest (or shared memory server) is started.  A guest may
-map the whole shared memory region or only part of it.
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 03/14] contrib/ivshmem-*: comply with QEMU coding style
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Fix coding style for structures.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   47 ++++++++++---------
 contrib/ivshmem-client/ivshmem-client.h |   76 +++++++++++++++----------------
 contrib/ivshmem-client/main.c           |   21 ++++-----
 contrib/ivshmem-server/ivshmem-server.c |   38 ++++++++--------
 contrib/ivshmem-server/ivshmem-server.h |   68 +++++++++++++--------------
 contrib/ivshmem-server/main.c           |   12 ++---
 6 files changed, 129 insertions(+), 133 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 2166b64..3f6ca98 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -31,7 +31,7 @@
 
 /* read message from the unix socket */
 static int
-read_one_msg(struct ivshmem_client *client, long *index, int *fd)
+read_one_msg(IvshmemClient *client, long *index, int *fd)
 {
     int ret;
     struct msghdr msg;
@@ -80,7 +80,7 @@ read_one_msg(struct ivshmem_client *client, long *index, int *fd)
 /* free a peer when the server advertise a disconnection or when the
  * client is freed */
 static void
-free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
+free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
 {
     unsigned vector;
 
@@ -94,9 +94,9 @@ free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
 
 /* handle message coming from server (new peer, new vectors) */
 static int
-handle_server_msg(struct ivshmem_client *client)
+handle_server_msg(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     long peer_id;
     int ret, fd;
 
@@ -146,7 +146,7 @@ handle_server_msg(struct ivshmem_client *client)
 
 /* init a new ivshmem client */
 int
-ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
+ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                     ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
                     int verbose)
 {
@@ -173,7 +173,7 @@ ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
 
 /* create and connect to the unix socket */
 int
-ivshmem_client_connect(struct ivshmem_client *client)
+ivshmem_client_connect(IvshmemClient *client)
 {
     struct sockaddr_un sun;
     int fd;
@@ -223,9 +223,9 @@ ivshmem_client_connect(struct ivshmem_client *client)
 
 /* close connection to the server, and free all peer structures */
 void
-ivshmem_client_close(struct ivshmem_client *client)
+ivshmem_client_close(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     unsigned i;
 
     debug_log(client, "close client\n");
@@ -244,8 +244,7 @@ ivshmem_client_close(struct ivshmem_client *client)
 
 /* get the fd_set according to the unix socket and peer list */
 void
-ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
-                       int *maxfd)
+ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds, int *maxfd)
 {
     int fd;
     unsigned vector;
@@ -266,9 +265,9 @@ ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
 
 /* handle events from eventfd: just print a message on notification */
 static int
-handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
+handle_event(IvshmemClient *client, const fd_set *cur, int maxfd)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     uint64_t kick;
     unsigned i;
     int ret;
@@ -301,7 +300,7 @@ handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
 
 /* read and handle new messages on the given fd_set */
 int
-ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
+ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd)
 {
     if (client->sock_fd < maxfd && FD_ISSET(client->sock_fd, fds) &&
         handle_server_msg(client) < 0 && errno != EINTR) {
@@ -317,8 +316,8 @@ ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
 
 /* send a notification on a vector of a peer */
 int
-ivshmem_client_notify(const struct ivshmem_client *client,
-                      const struct ivshmem_client_peer *peer, unsigned vector)
+ivshmem_client_notify(const IvshmemClient *client,
+                      const IvshmemClientPeer *peer, unsigned vector)
 {
     uint64_t kick;
     int fd;
@@ -342,8 +341,8 @@ ivshmem_client_notify(const struct ivshmem_client *client,
 
 /* send a notification to all vectors of a peer */
 int
-ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
-                                const struct ivshmem_client_peer *peer)
+ivshmem_client_notify_all_vects(const IvshmemClient *client,
+                                const IvshmemClientPeer *peer)
 {
     unsigned vector;
     int ret = 0;
@@ -359,9 +358,9 @@ ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
 
 /* send a notification to all peers */
 int
-ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
+ivshmem_client_notify_broadcast(const IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     int ret = 0;
 
     TAILQ_FOREACH(peer, &client->peer_list, next) {
@@ -374,10 +373,10 @@ ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
 }
 
 /* lookup peer from its id */
-struct ivshmem_client_peer *
-ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
+IvshmemClientPeer *
+ivshmem_client_search_peer(IvshmemClient *client, long peer_id)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
 
     if (peer_id == client->local.id) {
         return &client->local;
@@ -393,9 +392,9 @@ ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
 
 /* dump our info, the list of peers their vectors on stdout */
 void
-ivshmem_client_dump(const struct ivshmem_client *client)
+ivshmem_client_dump(const IvshmemClient *client)
 {
-    const struct ivshmem_client_peer *peer;
+    const IvshmemClientPeer *peer;
     unsigned vector;
 
     /* dump local infos */
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index d27222b..0fe0c94 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -33,29 +33,30 @@
  *
  * Each time a client connects to an ivshmem server, it is advertised to
  * all connected clients through the unix socket. When our ivshmem
- * client receives a notification, it creates a ivshmem_client_peer
+ * client receives a notification, it creates a IvshmemClientPeer
  * structure to store the infos of this peer.
  *
  * This structure is also used to store the information of our own
- * client in (struct ivshmem_client)->local.
+ * client in (IvshmemClient)->local.
  */
-struct ivshmem_client_peer {
-    TAILQ_ENTRY(ivshmem_client_peer) next;    /**< next in list*/
-    long id;                                    /**< the id of the peer */
-    int vectors[IVSHMEM_CLIENT_MAX_VECTORS];  /**< one fd per vector */
-    unsigned vectors_count;                     /**< number of vectors */
-};
-TAILQ_HEAD(ivshmem_client_peer_list, ivshmem_client_peer);
+typedef struct IvshmemClientPeer {
+    TAILQ_ENTRY(IvshmemClientPeer) next;     /**< next in list*/
+    long id;                                 /**< the id of the peer */
+    int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
+    unsigned vectors_count;                  /**< number of vectors */
+} IvshmemClientPeer;
+TAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
 
-struct ivshmem_client;
+typedef struct IvshmemClientPeerList IvshmemClientPeerList;
+typedef struct IvshmemClient IvshmemClient;
 
 /**
- * Typedef of callback function used when our ivshmem_client receives a
+ * Typedef of callback function used when our IvshmemClient receives a
  * notification from a peer.
  */
 typedef void (*ivshmem_client_notif_cb_t)(
-    const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer,
+    const IvshmemClient *client,
+    const IvshmemClientPeer *peer,
     unsigned vect, void *arg);
 
 /**
@@ -66,29 +67,29 @@ typedef void (*ivshmem_client_notif_cb_t)(
  * server, our own client information, and a pointer the notification
  * callback function used when we receive a notification from a peer.
  */
-struct ivshmem_client {
-    char unix_sock_path[PATH_MAX];        /**< path to unix sock */
-    int sock_fd;                          /**< unix sock filedesc */
+struct IvshmemClient {
+    char unix_sock_path[PATH_MAX];      /**< path to unix sock */
+    int sock_fd;                        /**< unix sock filedesc */
 
-    struct ivshmem_client_peer_list peer_list;  /**< list of peers */
-    struct ivshmem_client_peer local;   /**< our own infos */
+    IvshmemClientPeerList peer_list;    /**< list of peers */
+    IvshmemClientPeer local;            /**< our own infos */
 
     ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
-    void *notif_arg;                      /**< notification argument */
+    void *notif_arg;                    /**< notification argument */
 
-    int verbose;                          /**< true to enable debug */
+    int verbose;                        /**< true to enable debug */
 };
 
 /**
  * Initialize an ivshmem client
  *
  * @param client
- *   A pointer to an uninitialized ivshmem_client structure
+ *   A pointer to an uninitialized IvshmemClient structure
  * @param unix_sock_path
  *   The pointer to the unix socket file name
  * @param notif_cb
  *   If not NULL, the pointer to the function to be called when we our
- *   ivshmem_client receives a notification from a peer
+ *   IvshmemClient receives a notification from a peer
  * @param notif_arg
  *   Opaque pointer given as-is to the notification callback function
  * @param verbose
@@ -97,9 +98,9 @@ struct ivshmem_client {
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_client_init(struct ivshmem_client *client,
-    const char *unix_sock_path, ivshmem_client_notif_cb_t notif_cb,
-    void *notif_arg, int verbose);
+int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
+                        ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
+                        int verbose);
 
 /**
  * Connect to the server
@@ -114,7 +115,7 @@ int ivshmem_client_init(struct ivshmem_client *client,
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_client_connect(struct ivshmem_client *client);
+int ivshmem_client_connect(IvshmemClient *client);
 
 /**
  * Close connection to the server and free all peer structures
@@ -122,7 +123,7 @@ int ivshmem_client_connect(struct ivshmem_client *client);
  * @param client
  *   The ivshmem client
  */
-void ivshmem_client_close(struct ivshmem_client *client);
+void ivshmem_client_close(IvshmemClient *client);
 
 /**
  * Fill a fd_set with file descriptors to be monitored
@@ -140,7 +141,7 @@ void ivshmem_client_close(struct ivshmem_client *client);
  *   Must be set to the max file descriptor + 1 in fd_set. This value is
  *   updated if this function adds a greated fd in fd_set.
  */
-void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+void ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds,
                             int *maxfd);
 
 /**
@@ -161,8 +162,7 @@ void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
  * @return
  *   0 on success, negative value on failure.
  */
-int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
-    int maxfd);
+int ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd);
 
 /**
  * Send a notification to a vector of a peer
@@ -177,8 +177,8 @@ int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
  * @return
  *   0 on success, and a negative error on failure.
  */
-int ivshmem_client_notify(const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer, unsigned vector);
+int ivshmem_client_notify(const IvshmemClient *client,
+                          const IvshmemClientPeer *peer, unsigned vector);
 
 /**
  * Send a notification to all vectors of a peer
@@ -192,8 +192,8 @@ int ivshmem_client_notify(const struct ivshmem_client *client,
  *   0 on success, and a negative error on failure (at least one
  *   notification failed).
  */
-int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer);
+int ivshmem_client_notify_all_vects(const IvshmemClient *client,
+                                    const IvshmemClientPeer *peer);
 
 /**
  * Broadcat a notification to all vectors of all peers
@@ -205,7 +205,7 @@ int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
  *   0 on success, and a negative error on failure (at least one
  *   notification failed).
  */
-int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
+int ivshmem_client_notify_broadcast(const IvshmemClient *client);
 
 /**
  * Search a peer from its identifier
@@ -221,8 +221,8 @@ int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
  * @return
  *   The peer structure, or NULL if not found
  */
-struct ivshmem_client_peer *
-ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
+IvshmemClientPeer *
+ivshmem_client_search_peer(IvshmemClient *client, long peer_id);
 
 /**
  * Dump information of this ivshmem client on stdout
@@ -233,6 +233,6 @@ ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
  * @param client
  *   The ivshmem client
  */
-void ivshmem_client_dump(const struct ivshmem_client *client);
+void ivshmem_client_dump(const IvshmemClient *client);
 
 #endif /* _IVSHMEM_CLIENT_ */
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index 0d53f55..778d0f2 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -21,10 +21,10 @@
 #define DEFAULT_VERBOSE        0
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 
-struct ivshmem_client_args {
+typedef struct IvshmemClientArgs {
     int verbose;
     char *unix_sock_path;
-};
+} IvshmemClientArgs;
 
 /* show usage and exit with given error code */
 static void
@@ -41,7 +41,7 @@ usage(const char *name, int code)
 
 /* parse the program arguments, exit on error */
 static void
-parse_args(struct ivshmem_client_args *args, int argc, char *argv[])
+parse_args(IvshmemClientArgs *args, int argc, char *argv[])
 {
     char c;
 
@@ -83,9 +83,9 @@ cmdline_help(void)
 
 /* read stdin and handle commands */
 static int
-handle_stdin_command(struct ivshmem_client *client)
+handle_stdin_command(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     char buf[128];
     char *s, *token;
     int ret;
@@ -138,7 +138,7 @@ handle_stdin_command(struct ivshmem_client *client)
 /* listen on stdin (command line), on unix socket (notifications of new
  * and dead peers), and on eventfd (IRQ request) */
 int
-poll_events(struct ivshmem_client *client)
+poll_events(IvshmemClient *client)
 {
     fd_set fds;
     int ret, maxfd;
@@ -181,9 +181,8 @@ poll_events(struct ivshmem_client *client)
 
 /* callback when we receive a notification (just display it) */
 void
-notification_cb(const struct ivshmem_client *client,
-                const struct ivshmem_client_peer *peer, unsigned vect,
-                void *arg)
+notification_cb(const IvshmemClient *client, const IvshmemClientPeer *peer,
+                unsigned vect, void *arg)
 {
     (void)client;
     (void)arg;
@@ -194,8 +193,8 @@ int
 main(int argc, char *argv[])
 {
     struct sigaction sa;
-    struct ivshmem_client client;
-    struct ivshmem_client_args args = {
+    IvshmemClient client;
+    IvshmemClientArgs args = {
         .verbose = DEFAULT_VERBOSE,
         .unix_sock_path = DEFAULT_UNIX_SOCK_PATH,
     };
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index f6497bb..20fbac0 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -89,10 +89,10 @@ send_one_msg(int sock_fd, long peer_id, int fd)
 /* free a peer when the server advertise a disconnection or when the
  * server is freed */
 static void
-free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
+free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     unsigned vector;
-    struct ivshmem_server_peer *other_peer;
+    IvshmemServerPeer *other_peer;
 
     debug_log(server, "free peer %ld\n", peer->id);
     close(peer->sock_fd);
@@ -112,8 +112,7 @@ free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
 
 /* send the peer id and the shm_fd just after a new client connection */
 static int
-send_initial_info(struct ivshmem_server *server,
-                  struct ivshmem_server_peer *peer)
+send_initial_info(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     int ret;
 
@@ -136,9 +135,9 @@ send_initial_info(struct ivshmem_server *server,
 
 /* handle message on listening unix socket (new client connection) */
 static int
-handle_new_conn(struct ivshmem_server *server)
+handle_new_conn(IvshmemServer *server)
 {
-    struct ivshmem_server_peer *peer, *other_peer;
+    IvshmemServerPeer *peer, *other_peer;
     struct sockaddr_un unaddr;
     socklen_t unaddr_len;
     int newfd;
@@ -252,7 +251,7 @@ ivshmem_ftruncate(int fd, unsigned shmsize)
 
 /* Init a new ivshmem server */
 int
-ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
+ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
                     int verbose)
 {
@@ -274,7 +273,7 @@ ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
 
 /* open shm, create and bind to the unix socket */
 int
-ivshmem_server_start(struct ivshmem_server *server)
+ivshmem_server_start(IvshmemServer *server)
 {
     struct sockaddr_un sun;
     int shm_fd, sock_fd;
@@ -328,9 +327,9 @@ ivshmem_server_start(struct ivshmem_server *server)
 
 /* close connections to clients, the unix socket and the shm fd */
 void
-ivshmem_server_close(struct ivshmem_server *server)
+ivshmem_server_close(IvshmemServer *server)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     debug_log(server, "close server\n");
 
@@ -346,10 +345,9 @@ ivshmem_server_close(struct ivshmem_server *server)
 
 /* get the fd_set according to the unix socket and the peer list */
 void
-ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
-                       int *maxfd)
+ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     FD_SET(server->sock_fd, fds);
     if (server->sock_fd >= *maxfd) {
@@ -366,9 +364,9 @@ ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
 
 /* process incoming messages on the sockets in fd_set */
 int
-ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
+ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd)
 {
-    struct ivshmem_server_peer *peer, *peer_next;
+    IvshmemServerPeer *peer, *peer_next;
 
     if (server->sock_fd < maxfd && FD_ISSET(server->sock_fd, fds) &&
         handle_new_conn(server) < 0 && errno != EINTR) {
@@ -388,10 +386,10 @@ ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
 }
 
 /* lookup peer from its id */
-struct ivshmem_server_peer *
-ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
+IvshmemServerPeer *
+ivshmem_server_search_peer(IvshmemServer *server, long peer_id)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     TAILQ_FOREACH(peer, &server->peer_list, next) {
         if (peer->id == peer_id) {
@@ -403,9 +401,9 @@ ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
 
 /* dump our info, the list of peers their vectors on stdout */
 void
-ivshmem_server_dump(const struct ivshmem_server *server)
+ivshmem_server_dump(const IvshmemServer *server)
 {
-    const struct ivshmem_server_peer *peer;
+    const IvshmemServerPeer *peer;
     unsigned vector;
 
     /* dump peers */
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index cd74bbf..42736e4 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -39,18 +39,20 @@
  * Structure storing a peer
  *
  * Each time a client connects to an ivshmem server, a new
- * ivshmem_server_peer structure is created. This peer and all its
+ * IvshmemServerPeer structure is created. This peer and all its
  * vectors are advertised to all connected clients through the connected
  * unix sockets.
  */
-struct ivshmem_server_peer {
-    TAILQ_ENTRY(ivshmem_server_peer) next;    /**< next in list*/
-    int sock_fd;                                /**< connected unix sock */
-    long id;                                    /**< the id of the peer */
-    int vectors[IVSHMEM_SERVER_MAX_VECTORS];  /**< one fd per vector */
-    unsigned vectors_count;                     /**< number of vectors */
-};
-TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
+typedef struct IvshmemServerPeer {
+    TAILQ_ENTRY(IvshmemServerPeer) next;     /**< next in list*/
+    int sock_fd;                             /**< connected unix sock */
+    long id;                                 /**< the id of the peer */
+    int vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one fd per vector */
+    unsigned vectors_count;                  /**< number of vectors */
+} IvshmemServerPeer;
+TAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
+
+typedef struct IvshmemServerPeerList IvshmemServerPeerList;
 
 /**
  * Structure describing an ivshmem server
@@ -58,23 +60,23 @@ TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
  * This structure stores all information related to our server: the name
  * of the server unix socket and the list of connected peers.
  */
-struct ivshmem_server {
-    char unix_sock_path[PATH_MAX];  /**< path to unix socket */
-    int sock_fd;                    /**< unix sock file descriptor */
-    char shm_path[PATH_MAX];        /**< path to shm */
-    size_t shm_size;                /**< size of shm */
-    int shm_fd;                     /**< shm file descriptor */
-    unsigned n_vectors;             /**< number of vectors */
-    long cur_id;                    /**< id to be given to next client */
-    int verbose;                    /**< true in verbose mode */
-    struct ivshmem_server_peer_list peer_list;  /**< list of peers */
-};
+typedef struct IvshmemServer {
+    char unix_sock_path[PATH_MAX];   /**< path to unix socket */
+    int sock_fd;                     /**< unix sock file descriptor */
+    char shm_path[PATH_MAX];         /**< path to shm */
+    size_t shm_size;                 /**< size of shm */
+    int shm_fd;                      /**< shm file descriptor */
+    unsigned n_vectors;              /**< number of vectors */
+    long cur_id;                     /**< id to be given to next client */
+    int verbose;                     /**< true in verbose mode */
+    IvshmemServerPeerList peer_list; /**< list of peers */
+} IvshmemServer;
 
 /**
  * Initialize an ivshmem server
  *
  * @param server
- *   A pointer to an uninitialized ivshmem_server structure
+ *   A pointer to an uninitialized IvshmemServer structure
  * @param unix_sock_path
  *   The pointer to the unix socket file name
  * @param shm_path
@@ -92,20 +94,20 @@ struct ivshmem_server {
  *   0 on success, negative value on error
  */
 int
-ivshmem_server_init(struct ivshmem_server *server,
-    const char *unix_sock_path, const char *shm_path, size_t shm_size,
-    unsigned n_vectors, int verbose);
+ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
+                    const char *shm_path, size_t shm_size, unsigned n_vectors,
+                    int verbose);
 
 /**
  * Open the shm, then create and bind to the unix socket
  *
  * @param server
- *   The pointer to the initialized ivshmem server structure
+ *   The pointer to the initialized IvshmemServer structure
  *
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_server_start(struct ivshmem_server *server);
+int ivshmem_server_start(IvshmemServer *server);
 
 /**
  * Close the server
@@ -118,7 +120,7 @@ int ivshmem_server_start(struct ivshmem_server *server);
  * @param server
  *   The ivshmem server
  */
-void ivshmem_server_close(struct ivshmem_server *server);
+void ivshmem_server_close(IvshmemServer *server);
 
 /**
  * Fill a fd_set with file descriptors to be monitored
@@ -136,8 +138,7 @@ void ivshmem_server_close(struct ivshmem_server *server);
  *   updated if this function adds a greated fd in fd_set.
  */
 void
-ivshmem_server_get_fds(const struct ivshmem_server *server,
-    fd_set *fds, int *maxfd);
+ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd);
 
 /**
  * Read and handle new messages
@@ -157,8 +158,7 @@ ivshmem_server_get_fds(const struct ivshmem_server *server,
  * @return
  *   0 on success, negative value on failure.
  */
-int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
-    int maxfd);
+int ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd);
 
 /**
  * Search a peer from its identifier
@@ -171,8 +171,8 @@ int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
  * @return
  *   The peer structure, or NULL if not found
  */
-struct ivshmem_server_peer *
-ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
+IvshmemServerPeer *
+ivshmem_server_search_peer(IvshmemServer *server, long peer_id);
 
 /**
  * Dump information of this ivshmem server and its peers on stdout
@@ -180,6 +180,6 @@ ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
  * @param server
  *   The ivshmem server
  */
-void ivshmem_server_dump(const struct ivshmem_server *server);
+void ivshmem_server_dump(const IvshmemServer *server);
 
 #endif /* _IVSHMEM_SERVER_ */
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index 36b7028..a4504c3 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -29,7 +29,7 @@
 #define DEFAULT_N_VECTORS      16
 
 /* arguments given by the user */
-struct ivshmem_server_args {
+typedef struct IvshmemServerArgs {
     int verbose;
     int foreground;
     char *pid_file;
@@ -37,7 +37,7 @@ struct ivshmem_server_args {
     char *shm_path;
     size_t shm_size;
     unsigned n_vectors;
-};
+} IvshmemServerArgs;
 
 /* show usage and exit with given error code */
 static void
@@ -117,7 +117,7 @@ parse_uint(const char *val_str, unsigned *val)
 
 /* parse the program arguments, exit on error */
 static void
-parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
+parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 {
     char c;
 
@@ -192,7 +192,7 @@ parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
 /* wait for events on listening server unix socket and connected client
  * sockets */
 int
-poll_events(struct ivshmem_server *server)
+poll_events(IvshmemServer *server)
 {
     fd_set fds;
     int ret, maxfd;
@@ -229,9 +229,9 @@ poll_events(struct ivshmem_server *server)
 int
 main(int argc, char *argv[])
 {
-    struct ivshmem_server server;
+    IvshmemServer server;
     struct sigaction sa;
-    struct ivshmem_server_args args = {
+    IvshmemServerArgs args = {
         .verbose = DEFAULT_VERBOSE,
         .foreground = DEFAULT_FOREGROUND,
         .pid_file = DEFAULT_PID_FILE,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 03/14] contrib/ivshmem-*: comply with QEMU coding style
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Fix coding style for structures.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   47 ++++++++++---------
 contrib/ivshmem-client/ivshmem-client.h |   76 +++++++++++++++----------------
 contrib/ivshmem-client/main.c           |   21 ++++-----
 contrib/ivshmem-server/ivshmem-server.c |   38 ++++++++--------
 contrib/ivshmem-server/ivshmem-server.h |   68 +++++++++++++--------------
 contrib/ivshmem-server/main.c           |   12 ++---
 6 files changed, 129 insertions(+), 133 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 2166b64..3f6ca98 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -31,7 +31,7 @@
 
 /* read message from the unix socket */
 static int
-read_one_msg(struct ivshmem_client *client, long *index, int *fd)
+read_one_msg(IvshmemClient *client, long *index, int *fd)
 {
     int ret;
     struct msghdr msg;
@@ -80,7 +80,7 @@ read_one_msg(struct ivshmem_client *client, long *index, int *fd)
 /* free a peer when the server advertise a disconnection or when the
  * client is freed */
 static void
-free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
+free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
 {
     unsigned vector;
 
@@ -94,9 +94,9 @@ free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer)
 
 /* handle message coming from server (new peer, new vectors) */
 static int
-handle_server_msg(struct ivshmem_client *client)
+handle_server_msg(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     long peer_id;
     int ret, fd;
 
@@ -146,7 +146,7 @@ handle_server_msg(struct ivshmem_client *client)
 
 /* init a new ivshmem client */
 int
-ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
+ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                     ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
                     int verbose)
 {
@@ -173,7 +173,7 @@ ivshmem_client_init(struct ivshmem_client *client, const char *unix_sock_path,
 
 /* create and connect to the unix socket */
 int
-ivshmem_client_connect(struct ivshmem_client *client)
+ivshmem_client_connect(IvshmemClient *client)
 {
     struct sockaddr_un sun;
     int fd;
@@ -223,9 +223,9 @@ ivshmem_client_connect(struct ivshmem_client *client)
 
 /* close connection to the server, and free all peer structures */
 void
-ivshmem_client_close(struct ivshmem_client *client)
+ivshmem_client_close(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     unsigned i;
 
     debug_log(client, "close client\n");
@@ -244,8 +244,7 @@ ivshmem_client_close(struct ivshmem_client *client)
 
 /* get the fd_set according to the unix socket and peer list */
 void
-ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
-                       int *maxfd)
+ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds, int *maxfd)
 {
     int fd;
     unsigned vector;
@@ -266,9 +265,9 @@ ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
 
 /* handle events from eventfd: just print a message on notification */
 static int
-handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
+handle_event(IvshmemClient *client, const fd_set *cur, int maxfd)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     uint64_t kick;
     unsigned i;
     int ret;
@@ -301,7 +300,7 @@ handle_event(struct ivshmem_client *client, const fd_set *cur, int maxfd)
 
 /* read and handle new messages on the given fd_set */
 int
-ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
+ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd)
 {
     if (client->sock_fd < maxfd && FD_ISSET(client->sock_fd, fds) &&
         handle_server_msg(client) < 0 && errno != EINTR) {
@@ -317,8 +316,8 @@ ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds, int maxfd)
 
 /* send a notification on a vector of a peer */
 int
-ivshmem_client_notify(const struct ivshmem_client *client,
-                      const struct ivshmem_client_peer *peer, unsigned vector)
+ivshmem_client_notify(const IvshmemClient *client,
+                      const IvshmemClientPeer *peer, unsigned vector)
 {
     uint64_t kick;
     int fd;
@@ -342,8 +341,8 @@ ivshmem_client_notify(const struct ivshmem_client *client,
 
 /* send a notification to all vectors of a peer */
 int
-ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
-                                const struct ivshmem_client_peer *peer)
+ivshmem_client_notify_all_vects(const IvshmemClient *client,
+                                const IvshmemClientPeer *peer)
 {
     unsigned vector;
     int ret = 0;
@@ -359,9 +358,9 @@ ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
 
 /* send a notification to all peers */
 int
-ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
+ivshmem_client_notify_broadcast(const IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     int ret = 0;
 
     TAILQ_FOREACH(peer, &client->peer_list, next) {
@@ -374,10 +373,10 @@ ivshmem_client_notify_broadcast(const struct ivshmem_client *client)
 }
 
 /* lookup peer from its id */
-struct ivshmem_client_peer *
-ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
+IvshmemClientPeer *
+ivshmem_client_search_peer(IvshmemClient *client, long peer_id)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
 
     if (peer_id == client->local.id) {
         return &client->local;
@@ -393,9 +392,9 @@ ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id)
 
 /* dump our info, the list of peers their vectors on stdout */
 void
-ivshmem_client_dump(const struct ivshmem_client *client)
+ivshmem_client_dump(const IvshmemClient *client)
 {
-    const struct ivshmem_client_peer *peer;
+    const IvshmemClientPeer *peer;
     unsigned vector;
 
     /* dump local infos */
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index d27222b..0fe0c94 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -33,29 +33,30 @@
  *
  * Each time a client connects to an ivshmem server, it is advertised to
  * all connected clients through the unix socket. When our ivshmem
- * client receives a notification, it creates a ivshmem_client_peer
+ * client receives a notification, it creates a IvshmemClientPeer
  * structure to store the infos of this peer.
  *
  * This structure is also used to store the information of our own
- * client in (struct ivshmem_client)->local.
+ * client in (IvshmemClient)->local.
  */
-struct ivshmem_client_peer {
-    TAILQ_ENTRY(ivshmem_client_peer) next;    /**< next in list*/
-    long id;                                    /**< the id of the peer */
-    int vectors[IVSHMEM_CLIENT_MAX_VECTORS];  /**< one fd per vector */
-    unsigned vectors_count;                     /**< number of vectors */
-};
-TAILQ_HEAD(ivshmem_client_peer_list, ivshmem_client_peer);
+typedef struct IvshmemClientPeer {
+    TAILQ_ENTRY(IvshmemClientPeer) next;     /**< next in list*/
+    long id;                                 /**< the id of the peer */
+    int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
+    unsigned vectors_count;                  /**< number of vectors */
+} IvshmemClientPeer;
+TAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
 
-struct ivshmem_client;
+typedef struct IvshmemClientPeerList IvshmemClientPeerList;
+typedef struct IvshmemClient IvshmemClient;
 
 /**
- * Typedef of callback function used when our ivshmem_client receives a
+ * Typedef of callback function used when our IvshmemClient receives a
  * notification from a peer.
  */
 typedef void (*ivshmem_client_notif_cb_t)(
-    const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer,
+    const IvshmemClient *client,
+    const IvshmemClientPeer *peer,
     unsigned vect, void *arg);
 
 /**
@@ -66,29 +67,29 @@ typedef void (*ivshmem_client_notif_cb_t)(
  * server, our own client information, and a pointer the notification
  * callback function used when we receive a notification from a peer.
  */
-struct ivshmem_client {
-    char unix_sock_path[PATH_MAX];        /**< path to unix sock */
-    int sock_fd;                          /**< unix sock filedesc */
+struct IvshmemClient {
+    char unix_sock_path[PATH_MAX];      /**< path to unix sock */
+    int sock_fd;                        /**< unix sock filedesc */
 
-    struct ivshmem_client_peer_list peer_list;  /**< list of peers */
-    struct ivshmem_client_peer local;   /**< our own infos */
+    IvshmemClientPeerList peer_list;    /**< list of peers */
+    IvshmemClientPeer local;            /**< our own infos */
 
     ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
-    void *notif_arg;                      /**< notification argument */
+    void *notif_arg;                    /**< notification argument */
 
-    int verbose;                          /**< true to enable debug */
+    int verbose;                        /**< true to enable debug */
 };
 
 /**
  * Initialize an ivshmem client
  *
  * @param client
- *   A pointer to an uninitialized ivshmem_client structure
+ *   A pointer to an uninitialized IvshmemClient structure
  * @param unix_sock_path
  *   The pointer to the unix socket file name
  * @param notif_cb
  *   If not NULL, the pointer to the function to be called when we our
- *   ivshmem_client receives a notification from a peer
+ *   IvshmemClient receives a notification from a peer
  * @param notif_arg
  *   Opaque pointer given as-is to the notification callback function
  * @param verbose
@@ -97,9 +98,9 @@ struct ivshmem_client {
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_client_init(struct ivshmem_client *client,
-    const char *unix_sock_path, ivshmem_client_notif_cb_t notif_cb,
-    void *notif_arg, int verbose);
+int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
+                        ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
+                        int verbose);
 
 /**
  * Connect to the server
@@ -114,7 +115,7 @@ int ivshmem_client_init(struct ivshmem_client *client,
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_client_connect(struct ivshmem_client *client);
+int ivshmem_client_connect(IvshmemClient *client);
 
 /**
  * Close connection to the server and free all peer structures
@@ -122,7 +123,7 @@ int ivshmem_client_connect(struct ivshmem_client *client);
  * @param client
  *   The ivshmem client
  */
-void ivshmem_client_close(struct ivshmem_client *client);
+void ivshmem_client_close(IvshmemClient *client);
 
 /**
  * Fill a fd_set with file descriptors to be monitored
@@ -140,7 +141,7 @@ void ivshmem_client_close(struct ivshmem_client *client);
  *   Must be set to the max file descriptor + 1 in fd_set. This value is
  *   updated if this function adds a greated fd in fd_set.
  */
-void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
+void ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds,
                             int *maxfd);
 
 /**
@@ -161,8 +162,7 @@ void ivshmem_client_get_fds(const struct ivshmem_client *client, fd_set *fds,
  * @return
  *   0 on success, negative value on failure.
  */
-int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
-    int maxfd);
+int ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd);
 
 /**
  * Send a notification to a vector of a peer
@@ -177,8 +177,8 @@ int ivshmem_client_handle_fds(struct ivshmem_client *client, fd_set *fds,
  * @return
  *   0 on success, and a negative error on failure.
  */
-int ivshmem_client_notify(const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer, unsigned vector);
+int ivshmem_client_notify(const IvshmemClient *client,
+                          const IvshmemClientPeer *peer, unsigned vector);
 
 /**
  * Send a notification to all vectors of a peer
@@ -192,8 +192,8 @@ int ivshmem_client_notify(const struct ivshmem_client *client,
  *   0 on success, and a negative error on failure (at least one
  *   notification failed).
  */
-int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
-    const struct ivshmem_client_peer *peer);
+int ivshmem_client_notify_all_vects(const IvshmemClient *client,
+                                    const IvshmemClientPeer *peer);
 
 /**
  * Broadcat a notification to all vectors of all peers
@@ -205,7 +205,7 @@ int ivshmem_client_notify_all_vects(const struct ivshmem_client *client,
  *   0 on success, and a negative error on failure (at least one
  *   notification failed).
  */
-int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
+int ivshmem_client_notify_broadcast(const IvshmemClient *client);
 
 /**
  * Search a peer from its identifier
@@ -221,8 +221,8 @@ int ivshmem_client_notify_broadcast(const struct ivshmem_client *client);
  * @return
  *   The peer structure, or NULL if not found
  */
-struct ivshmem_client_peer *
-ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
+IvshmemClientPeer *
+ivshmem_client_search_peer(IvshmemClient *client, long peer_id);
 
 /**
  * Dump information of this ivshmem client on stdout
@@ -233,6 +233,6 @@ ivshmem_client_search_peer(struct ivshmem_client *client, long peer_id);
  * @param client
  *   The ivshmem client
  */
-void ivshmem_client_dump(const struct ivshmem_client *client);
+void ivshmem_client_dump(const IvshmemClient *client);
 
 #endif /* _IVSHMEM_CLIENT_ */
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index 0d53f55..778d0f2 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -21,10 +21,10 @@
 #define DEFAULT_VERBOSE        0
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 
-struct ivshmem_client_args {
+typedef struct IvshmemClientArgs {
     int verbose;
     char *unix_sock_path;
-};
+} IvshmemClientArgs;
 
 /* show usage and exit with given error code */
 static void
@@ -41,7 +41,7 @@ usage(const char *name, int code)
 
 /* parse the program arguments, exit on error */
 static void
-parse_args(struct ivshmem_client_args *args, int argc, char *argv[])
+parse_args(IvshmemClientArgs *args, int argc, char *argv[])
 {
     char c;
 
@@ -83,9 +83,9 @@ cmdline_help(void)
 
 /* read stdin and handle commands */
 static int
-handle_stdin_command(struct ivshmem_client *client)
+handle_stdin_command(IvshmemClient *client)
 {
-    struct ivshmem_client_peer *peer;
+    IvshmemClientPeer *peer;
     char buf[128];
     char *s, *token;
     int ret;
@@ -138,7 +138,7 @@ handle_stdin_command(struct ivshmem_client *client)
 /* listen on stdin (command line), on unix socket (notifications of new
  * and dead peers), and on eventfd (IRQ request) */
 int
-poll_events(struct ivshmem_client *client)
+poll_events(IvshmemClient *client)
 {
     fd_set fds;
     int ret, maxfd;
@@ -181,9 +181,8 @@ poll_events(struct ivshmem_client *client)
 
 /* callback when we receive a notification (just display it) */
 void
-notification_cb(const struct ivshmem_client *client,
-                const struct ivshmem_client_peer *peer, unsigned vect,
-                void *arg)
+notification_cb(const IvshmemClient *client, const IvshmemClientPeer *peer,
+                unsigned vect, void *arg)
 {
     (void)client;
     (void)arg;
@@ -194,8 +193,8 @@ int
 main(int argc, char *argv[])
 {
     struct sigaction sa;
-    struct ivshmem_client client;
-    struct ivshmem_client_args args = {
+    IvshmemClient client;
+    IvshmemClientArgs args = {
         .verbose = DEFAULT_VERBOSE,
         .unix_sock_path = DEFAULT_UNIX_SOCK_PATH,
     };
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index f6497bb..20fbac0 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -89,10 +89,10 @@ send_one_msg(int sock_fd, long peer_id, int fd)
 /* free a peer when the server advertise a disconnection or when the
  * server is freed */
 static void
-free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
+free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     unsigned vector;
-    struct ivshmem_server_peer *other_peer;
+    IvshmemServerPeer *other_peer;
 
     debug_log(server, "free peer %ld\n", peer->id);
     close(peer->sock_fd);
@@ -112,8 +112,7 @@ free_peer(struct ivshmem_server *server, struct ivshmem_server_peer *peer)
 
 /* send the peer id and the shm_fd just after a new client connection */
 static int
-send_initial_info(struct ivshmem_server *server,
-                  struct ivshmem_server_peer *peer)
+send_initial_info(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     int ret;
 
@@ -136,9 +135,9 @@ send_initial_info(struct ivshmem_server *server,
 
 /* handle message on listening unix socket (new client connection) */
 static int
-handle_new_conn(struct ivshmem_server *server)
+handle_new_conn(IvshmemServer *server)
 {
-    struct ivshmem_server_peer *peer, *other_peer;
+    IvshmemServerPeer *peer, *other_peer;
     struct sockaddr_un unaddr;
     socklen_t unaddr_len;
     int newfd;
@@ -252,7 +251,7 @@ ivshmem_ftruncate(int fd, unsigned shmsize)
 
 /* Init a new ivshmem server */
 int
-ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
+ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
                     int verbose)
 {
@@ -274,7 +273,7 @@ ivshmem_server_init(struct ivshmem_server *server, const char *unix_sock_path,
 
 /* open shm, create and bind to the unix socket */
 int
-ivshmem_server_start(struct ivshmem_server *server)
+ivshmem_server_start(IvshmemServer *server)
 {
     struct sockaddr_un sun;
     int shm_fd, sock_fd;
@@ -328,9 +327,9 @@ ivshmem_server_start(struct ivshmem_server *server)
 
 /* close connections to clients, the unix socket and the shm fd */
 void
-ivshmem_server_close(struct ivshmem_server *server)
+ivshmem_server_close(IvshmemServer *server)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     debug_log(server, "close server\n");
 
@@ -346,10 +345,9 @@ ivshmem_server_close(struct ivshmem_server *server)
 
 /* get the fd_set according to the unix socket and the peer list */
 void
-ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
-                       int *maxfd)
+ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     FD_SET(server->sock_fd, fds);
     if (server->sock_fd >= *maxfd) {
@@ -366,9 +364,9 @@ ivshmem_server_get_fds(const struct ivshmem_server *server, fd_set *fds,
 
 /* process incoming messages on the sockets in fd_set */
 int
-ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
+ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd)
 {
-    struct ivshmem_server_peer *peer, *peer_next;
+    IvshmemServerPeer *peer, *peer_next;
 
     if (server->sock_fd < maxfd && FD_ISSET(server->sock_fd, fds) &&
         handle_new_conn(server) < 0 && errno != EINTR) {
@@ -388,10 +386,10 @@ ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds, int maxfd)
 }
 
 /* lookup peer from its id */
-struct ivshmem_server_peer *
-ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
+IvshmemServerPeer *
+ivshmem_server_search_peer(IvshmemServer *server, long peer_id)
 {
-    struct ivshmem_server_peer *peer;
+    IvshmemServerPeer *peer;
 
     TAILQ_FOREACH(peer, &server->peer_list, next) {
         if (peer->id == peer_id) {
@@ -403,9 +401,9 @@ ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id)
 
 /* dump our info, the list of peers their vectors on stdout */
 void
-ivshmem_server_dump(const struct ivshmem_server *server)
+ivshmem_server_dump(const IvshmemServer *server)
 {
-    const struct ivshmem_server_peer *peer;
+    const IvshmemServerPeer *peer;
     unsigned vector;
 
     /* dump peers */
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index cd74bbf..42736e4 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -39,18 +39,20 @@
  * Structure storing a peer
  *
  * Each time a client connects to an ivshmem server, a new
- * ivshmem_server_peer structure is created. This peer and all its
+ * IvshmemServerPeer structure is created. This peer and all its
  * vectors are advertised to all connected clients through the connected
  * unix sockets.
  */
-struct ivshmem_server_peer {
-    TAILQ_ENTRY(ivshmem_server_peer) next;    /**< next in list*/
-    int sock_fd;                                /**< connected unix sock */
-    long id;                                    /**< the id of the peer */
-    int vectors[IVSHMEM_SERVER_MAX_VECTORS];  /**< one fd per vector */
-    unsigned vectors_count;                     /**< number of vectors */
-};
-TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
+typedef struct IvshmemServerPeer {
+    TAILQ_ENTRY(IvshmemServerPeer) next;     /**< next in list*/
+    int sock_fd;                             /**< connected unix sock */
+    long id;                                 /**< the id of the peer */
+    int vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one fd per vector */
+    unsigned vectors_count;                  /**< number of vectors */
+} IvshmemServerPeer;
+TAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
+
+typedef struct IvshmemServerPeerList IvshmemServerPeerList;
 
 /**
  * Structure describing an ivshmem server
@@ -58,23 +60,23 @@ TAILQ_HEAD(ivshmem_server_peer_list, ivshmem_server_peer);
  * This structure stores all information related to our server: the name
  * of the server unix socket and the list of connected peers.
  */
-struct ivshmem_server {
-    char unix_sock_path[PATH_MAX];  /**< path to unix socket */
-    int sock_fd;                    /**< unix sock file descriptor */
-    char shm_path[PATH_MAX];        /**< path to shm */
-    size_t shm_size;                /**< size of shm */
-    int shm_fd;                     /**< shm file descriptor */
-    unsigned n_vectors;             /**< number of vectors */
-    long cur_id;                    /**< id to be given to next client */
-    int verbose;                    /**< true in verbose mode */
-    struct ivshmem_server_peer_list peer_list;  /**< list of peers */
-};
+typedef struct IvshmemServer {
+    char unix_sock_path[PATH_MAX];   /**< path to unix socket */
+    int sock_fd;                     /**< unix sock file descriptor */
+    char shm_path[PATH_MAX];         /**< path to shm */
+    size_t shm_size;                 /**< size of shm */
+    int shm_fd;                      /**< shm file descriptor */
+    unsigned n_vectors;              /**< number of vectors */
+    long cur_id;                     /**< id to be given to next client */
+    int verbose;                     /**< true in verbose mode */
+    IvshmemServerPeerList peer_list; /**< list of peers */
+} IvshmemServer;
 
 /**
  * Initialize an ivshmem server
  *
  * @param server
- *   A pointer to an uninitialized ivshmem_server structure
+ *   A pointer to an uninitialized IvshmemServer structure
  * @param unix_sock_path
  *   The pointer to the unix socket file name
  * @param shm_path
@@ -92,20 +94,20 @@ struct ivshmem_server {
  *   0 on success, negative value on error
  */
 int
-ivshmem_server_init(struct ivshmem_server *server,
-    const char *unix_sock_path, const char *shm_path, size_t shm_size,
-    unsigned n_vectors, int verbose);
+ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
+                    const char *shm_path, size_t shm_size, unsigned n_vectors,
+                    int verbose);
 
 /**
  * Open the shm, then create and bind to the unix socket
  *
  * @param server
- *   The pointer to the initialized ivshmem server structure
+ *   The pointer to the initialized IvshmemServer structure
  *
  * @return
  *   0 on success, or a negative value on error
  */
-int ivshmem_server_start(struct ivshmem_server *server);
+int ivshmem_server_start(IvshmemServer *server);
 
 /**
  * Close the server
@@ -118,7 +120,7 @@ int ivshmem_server_start(struct ivshmem_server *server);
  * @param server
  *   The ivshmem server
  */
-void ivshmem_server_close(struct ivshmem_server *server);
+void ivshmem_server_close(IvshmemServer *server);
 
 /**
  * Fill a fd_set with file descriptors to be monitored
@@ -136,8 +138,7 @@ void ivshmem_server_close(struct ivshmem_server *server);
  *   updated if this function adds a greated fd in fd_set.
  */
 void
-ivshmem_server_get_fds(const struct ivshmem_server *server,
-    fd_set *fds, int *maxfd);
+ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd);
 
 /**
  * Read and handle new messages
@@ -157,8 +158,7 @@ ivshmem_server_get_fds(const struct ivshmem_server *server,
  * @return
  *   0 on success, negative value on failure.
  */
-int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
-    int maxfd);
+int ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd);
 
 /**
  * Search a peer from its identifier
@@ -171,8 +171,8 @@ int ivshmem_server_handle_fds(struct ivshmem_server *server, fd_set *fds,
  * @return
  *   The peer structure, or NULL if not found
  */
-struct ivshmem_server_peer *
-ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
+IvshmemServerPeer *
+ivshmem_server_search_peer(IvshmemServer *server, long peer_id);
 
 /**
  * Dump information of this ivshmem server and its peers on stdout
@@ -180,6 +180,6 @@ ivshmem_server_search_peer(struct ivshmem_server *server, long peer_id);
  * @param server
  *   The ivshmem server
  */
-void ivshmem_server_dump(const struct ivshmem_server *server);
+void ivshmem_server_dump(const IvshmemServer *server);
 
 #endif /* _IVSHMEM_SERVER_ */
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index 36b7028..a4504c3 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -29,7 +29,7 @@
 #define DEFAULT_N_VECTORS      16
 
 /* arguments given by the user */
-struct ivshmem_server_args {
+typedef struct IvshmemServerArgs {
     int verbose;
     int foreground;
     char *pid_file;
@@ -37,7 +37,7 @@ struct ivshmem_server_args {
     char *shm_path;
     size_t shm_size;
     unsigned n_vectors;
-};
+} IvshmemServerArgs;
 
 /* show usage and exit with given error code */
 static void
@@ -117,7 +117,7 @@ parse_uint(const char *val_str, unsigned *val)
 
 /* parse the program arguments, exit on error */
 static void
-parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
+parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 {
     char c;
 
@@ -192,7 +192,7 @@ parse_args(struct ivshmem_server_args *args, int argc, char *argv[])
 /* wait for events on listening server unix socket and connected client
  * sockets */
 int
-poll_events(struct ivshmem_server *server)
+poll_events(IvshmemServer *server)
 {
     fd_set fds;
     int ret, maxfd;
@@ -229,9 +229,9 @@ poll_events(struct ivshmem_server *server)
 int
 main(int argc, char *argv[])
 {
-    struct ivshmem_server server;
+    IvshmemServer server;
     struct sigaction sa;
-    struct ivshmem_server_args args = {
+    IvshmemServerArgs args = {
         .verbose = DEFAULT_VERBOSE,
         .foreground = DEFAULT_FOREGROUND,
         .pid_file = DEFAULT_PID_FILE,
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 04/14] contrib/ivshmem-*: reuse qemu/queue.h
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Switch to qemu/queue.h strutures.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   17 ++++++++--------
 contrib/ivshmem-client/ivshmem-client.h |    7 ++++---
 contrib/ivshmem-server/ivshmem-server.c |   33 ++++++++++++-------------------
 contrib/ivshmem-server/ivshmem-server.h |    7 ++++---
 4 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 3f6ca98..ce3a5d2 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -14,12 +14,13 @@
 #include <signal.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <sys/queue.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "qemu/queue.h"
+
 #include "ivshmem-client.h"
 
 /* log a message on stdout if verbose=1 */
@@ -84,7 +85,7 @@ free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
 {
     unsigned vector;
 
-    TAILQ_REMOVE(&client->peer_list, peer, next);
+    QTAILQ_REMOVE(&client->peer_list, peer, next);
     for (vector = 0; vector < peer->vectors_count; vector++) {
         close(peer->vectors[vector]);
     }
@@ -131,7 +132,7 @@ handle_server_msg(IvshmemClient *client)
         memset(peer, 0, sizeof(*peer));
         peer->id = peer_id;
         peer->vectors_count = 0;
-        TAILQ_INSERT_TAIL(&client->peer_list, peer, next);
+        QTAILQ_INSERT_TAIL(&client->peer_list, peer, next);
         debug_log(client, "new peer id = %ld\n", peer_id);
     }
 
@@ -161,7 +162,7 @@ ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
         client->local.vectors[i] = -1;
     }
 
-    TAILQ_INIT(&client->peer_list);
+    QTAILQ_INIT(&client->peer_list);
     client->local.id = -1;
 
     client->notif_cb = notif_cb;
@@ -230,7 +231,7 @@ ivshmem_client_close(IvshmemClient *client)
 
     debug_log(client, "close client\n");
 
-    while ((peer = TAILQ_FIRST(&client->peer_list)) != NULL) {
+    while ((peer = QTAILQ_FIRST(&client->peer_list)) != NULL) {
         free_peer(client, peer);
     }
 
@@ -363,7 +364,7 @@ ivshmem_client_notify_broadcast(const IvshmemClient *client)
     IvshmemClientPeer *peer;
     int ret = 0;
 
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         if (ivshmem_client_notify_all_vects(client, peer) < 0) {
             ret = -1;
         }
@@ -382,7 +383,7 @@ ivshmem_client_search_peer(IvshmemClient *client, long peer_id)
         return &client->local;
     }
 
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         if (peer->id == peer_id) {
             return peer;
         }
@@ -406,7 +407,7 @@ ivshmem_client_dump(const IvshmemClient *client)
     }
 
     /* dump peers */
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         printf("peer_id = %ld\n", peer->id);
 
         for (vector = 0; vector < peer->vectors_count; vector++) {
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index 0fe0c94..e3b284d 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -21,7 +21,8 @@
 
 #include <limits.h>
 #include <sys/select.h>
-#include <sys/queue.h>
+
+#include "qemu/queue.h"
 
 /**
  * Maximum number of notification vectors supported by the client
@@ -40,12 +41,12 @@
  * client in (IvshmemClient)->local.
  */
 typedef struct IvshmemClientPeer {
-    TAILQ_ENTRY(IvshmemClientPeer) next;     /**< next in list*/
+    QTAILQ_ENTRY(IvshmemClientPeer) next;    /**< next in list*/
     long id;                                 /**< the id of the peer */
     int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
     unsigned vectors_count;                  /**< number of vectors */
 } IvshmemClientPeer;
-TAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
+QTAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
 
 typedef struct IvshmemClientPeerList IvshmemClientPeerList;
 typedef struct IvshmemClient IvshmemClient;
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 20fbac0..e58864d 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -16,7 +16,6 @@
 #include <inttypes.h>
 #include <fcntl.h>
 
-#include <sys/queue.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -24,6 +23,8 @@
 #include <sys/un.h>
 #include <sys/eventfd.h>
 
+#include "qemu/queue.h"
+
 #include "ivshmem-server.h"
 
 /* log a message on stdout if verbose=1 */
@@ -33,14 +34,6 @@
         }                                \
     } while (0)
 
-/* browse the queue, allowing to remove/free the current element */
-#define    TAILQ_FOREACH_SAFE(var, var2, head, field)            \
-    for ((var) = TAILQ_FIRST((head)),                            \
-             (var2) = ((var) ? TAILQ_NEXT((var), field) : NULL); \
-         (var);                                                  \
-         (var) = (var2),                                         \
-             (var2) = ((var2) ? TAILQ_NEXT((var2), field) : NULL))
-
 /** maximum size of a huge page, used by ivshmem_ftruncate() */
 #define MAX_HUGEPAGE_SIZE (1024 * 1024 * 1024)
 
@@ -96,10 +89,10 @@ free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
 
     debug_log(server, "free peer %ld\n", peer->id);
     close(peer->sock_fd);
-    TAILQ_REMOVE(&server->peer_list, peer, next);
+    QTAILQ_REMOVE(&server->peer_list, peer, next);
 
     /* advertise the deletion to other peers */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         send_one_msg(other_peer->sock_fd, peer->id, -1);
     }
 
@@ -188,14 +181,14 @@ handle_new_conn(IvshmemServer *server)
     }
 
     /* advertise the new peer to others */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         for (i = 0; i < peer->vectors_count; i++) {
             send_one_msg(other_peer->sock_fd, peer->id, peer->vectors[i]);
         }
     }
 
     /* advertise the other peers to the new one */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         for (i = 0; i < peer->vectors_count; i++) {
             send_one_msg(peer->sock_fd, other_peer->id, other_peer->vectors[i]);
         }
@@ -206,7 +199,7 @@ handle_new_conn(IvshmemServer *server)
         send_one_msg(peer->sock_fd, peer->id, peer->vectors[i]);
     }
 
-    TAILQ_INSERT_TAIL(&server->peer_list, peer, next);
+    QTAILQ_INSERT_TAIL(&server->peer_list, peer, next);
     debug_log(server, "new peer id = %ld\n", peer->id);
     return 0;
 
@@ -266,7 +259,7 @@ ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
     server->n_vectors = n_vectors;
     server->verbose = verbose;
 
-    TAILQ_INIT(&server->peer_list);
+    QTAILQ_INIT(&server->peer_list);
 
     return 0;
 }
@@ -333,7 +326,7 @@ ivshmem_server_close(IvshmemServer *server)
 
     debug_log(server, "close server\n");
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         free_peer(server, peer);
     }
 
@@ -354,7 +347,7 @@ ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd)
         *maxfd = server->sock_fd + 1;
     }
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         FD_SET(peer->sock_fd, fds);
         if (peer->sock_fd >= *maxfd) {
             *maxfd = peer->sock_fd + 1;
@@ -374,7 +367,7 @@ ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd)
         return -1;
     }
 
-    TAILQ_FOREACH_SAFE(peer, peer_next, &server->peer_list, next) {
+    QTAILQ_FOREACH_SAFE(peer, &server->peer_list, next, peer_next) {
         /* any message from a peer socket result in a close() */
         debug_log(server, "peer->sock_fd=%d\n", peer->sock_fd);
         if (peer->sock_fd < maxfd && FD_ISSET(peer->sock_fd, fds)) {
@@ -391,7 +384,7 @@ ivshmem_server_search_peer(IvshmemServer *server, long peer_id)
 {
     IvshmemServerPeer *peer;
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         if (peer->id == peer_id) {
             return peer;
         }
@@ -407,7 +400,7 @@ ivshmem_server_dump(const IvshmemServer *server)
     unsigned vector;
 
     /* dump peers */
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         printf("peer_id = %ld\n", peer->id);
 
         for (vector = 0; vector < peer->vectors_count; vector++) {
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index 42736e4..acd17a8 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -28,7 +28,8 @@
 
 #include <limits.h>
 #include <sys/select.h>
-#include <sys/queue.h>
+
+#include "qemu/queue.h"
 
 /**
  * Maximum number of notification vectors supported by the server
@@ -44,13 +45,13 @@
  * unix sockets.
  */
 typedef struct IvshmemServerPeer {
-    TAILQ_ENTRY(IvshmemServerPeer) next;     /**< next in list*/
+    QTAILQ_ENTRY(IvshmemServerPeer) next;    /**< next in list*/
     int sock_fd;                             /**< connected unix sock */
     long id;                                 /**< the id of the peer */
     int vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one fd per vector */
     unsigned vectors_count;                  /**< number of vectors */
 } IvshmemServerPeer;
-TAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
+QTAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
 
 typedef struct IvshmemServerPeerList IvshmemServerPeerList;
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 04/14] contrib/ivshmem-*: reuse qemu/queue.h
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Switch to qemu/queue.h strutures.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   17 ++++++++--------
 contrib/ivshmem-client/ivshmem-client.h |    7 ++++---
 contrib/ivshmem-server/ivshmem-server.c |   33 ++++++++++++-------------------
 contrib/ivshmem-server/ivshmem-server.h |    7 ++++---
 4 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 3f6ca98..ce3a5d2 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -14,12 +14,13 @@
 #include <signal.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <sys/queue.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "qemu/queue.h"
+
 #include "ivshmem-client.h"
 
 /* log a message on stdout if verbose=1 */
@@ -84,7 +85,7 @@ free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
 {
     unsigned vector;
 
-    TAILQ_REMOVE(&client->peer_list, peer, next);
+    QTAILQ_REMOVE(&client->peer_list, peer, next);
     for (vector = 0; vector < peer->vectors_count; vector++) {
         close(peer->vectors[vector]);
     }
@@ -131,7 +132,7 @@ handle_server_msg(IvshmemClient *client)
         memset(peer, 0, sizeof(*peer));
         peer->id = peer_id;
         peer->vectors_count = 0;
-        TAILQ_INSERT_TAIL(&client->peer_list, peer, next);
+        QTAILQ_INSERT_TAIL(&client->peer_list, peer, next);
         debug_log(client, "new peer id = %ld\n", peer_id);
     }
 
@@ -161,7 +162,7 @@ ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
         client->local.vectors[i] = -1;
     }
 
-    TAILQ_INIT(&client->peer_list);
+    QTAILQ_INIT(&client->peer_list);
     client->local.id = -1;
 
     client->notif_cb = notif_cb;
@@ -230,7 +231,7 @@ ivshmem_client_close(IvshmemClient *client)
 
     debug_log(client, "close client\n");
 
-    while ((peer = TAILQ_FIRST(&client->peer_list)) != NULL) {
+    while ((peer = QTAILQ_FIRST(&client->peer_list)) != NULL) {
         free_peer(client, peer);
     }
 
@@ -363,7 +364,7 @@ ivshmem_client_notify_broadcast(const IvshmemClient *client)
     IvshmemClientPeer *peer;
     int ret = 0;
 
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         if (ivshmem_client_notify_all_vects(client, peer) < 0) {
             ret = -1;
         }
@@ -382,7 +383,7 @@ ivshmem_client_search_peer(IvshmemClient *client, long peer_id)
         return &client->local;
     }
 
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         if (peer->id == peer_id) {
             return peer;
         }
@@ -406,7 +407,7 @@ ivshmem_client_dump(const IvshmemClient *client)
     }
 
     /* dump peers */
-    TAILQ_FOREACH(peer, &client->peer_list, next) {
+    QTAILQ_FOREACH(peer, &client->peer_list, next) {
         printf("peer_id = %ld\n", peer->id);
 
         for (vector = 0; vector < peer->vectors_count; vector++) {
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index 0fe0c94..e3b284d 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -21,7 +21,8 @@
 
 #include <limits.h>
 #include <sys/select.h>
-#include <sys/queue.h>
+
+#include "qemu/queue.h"
 
 /**
  * Maximum number of notification vectors supported by the client
@@ -40,12 +41,12 @@
  * client in (IvshmemClient)->local.
  */
 typedef struct IvshmemClientPeer {
-    TAILQ_ENTRY(IvshmemClientPeer) next;     /**< next in list*/
+    QTAILQ_ENTRY(IvshmemClientPeer) next;    /**< next in list*/
     long id;                                 /**< the id of the peer */
     int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
     unsigned vectors_count;                  /**< number of vectors */
 } IvshmemClientPeer;
-TAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
+QTAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
 
 typedef struct IvshmemClientPeerList IvshmemClientPeerList;
 typedef struct IvshmemClient IvshmemClient;
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 20fbac0..e58864d 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -16,7 +16,6 @@
 #include <inttypes.h>
 #include <fcntl.h>
 
-#include <sys/queue.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -24,6 +23,8 @@
 #include <sys/un.h>
 #include <sys/eventfd.h>
 
+#include "qemu/queue.h"
+
 #include "ivshmem-server.h"
 
 /* log a message on stdout if verbose=1 */
@@ -33,14 +34,6 @@
         }                                \
     } while (0)
 
-/* browse the queue, allowing to remove/free the current element */
-#define    TAILQ_FOREACH_SAFE(var, var2, head, field)            \
-    for ((var) = TAILQ_FIRST((head)),                            \
-             (var2) = ((var) ? TAILQ_NEXT((var), field) : NULL); \
-         (var);                                                  \
-         (var) = (var2),                                         \
-             (var2) = ((var2) ? TAILQ_NEXT((var2), field) : NULL))
-
 /** maximum size of a huge page, used by ivshmem_ftruncate() */
 #define MAX_HUGEPAGE_SIZE (1024 * 1024 * 1024)
 
@@ -96,10 +89,10 @@ free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
 
     debug_log(server, "free peer %ld\n", peer->id);
     close(peer->sock_fd);
-    TAILQ_REMOVE(&server->peer_list, peer, next);
+    QTAILQ_REMOVE(&server->peer_list, peer, next);
 
     /* advertise the deletion to other peers */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         send_one_msg(other_peer->sock_fd, peer->id, -1);
     }
 
@@ -188,14 +181,14 @@ handle_new_conn(IvshmemServer *server)
     }
 
     /* advertise the new peer to others */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         for (i = 0; i < peer->vectors_count; i++) {
             send_one_msg(other_peer->sock_fd, peer->id, peer->vectors[i]);
         }
     }
 
     /* advertise the other peers to the new one */
-    TAILQ_FOREACH(other_peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
         for (i = 0; i < peer->vectors_count; i++) {
             send_one_msg(peer->sock_fd, other_peer->id, other_peer->vectors[i]);
         }
@@ -206,7 +199,7 @@ handle_new_conn(IvshmemServer *server)
         send_one_msg(peer->sock_fd, peer->id, peer->vectors[i]);
     }
 
-    TAILQ_INSERT_TAIL(&server->peer_list, peer, next);
+    QTAILQ_INSERT_TAIL(&server->peer_list, peer, next);
     debug_log(server, "new peer id = %ld\n", peer->id);
     return 0;
 
@@ -266,7 +259,7 @@ ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
     server->n_vectors = n_vectors;
     server->verbose = verbose;
 
-    TAILQ_INIT(&server->peer_list);
+    QTAILQ_INIT(&server->peer_list);
 
     return 0;
 }
@@ -333,7 +326,7 @@ ivshmem_server_close(IvshmemServer *server)
 
     debug_log(server, "close server\n");
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         free_peer(server, peer);
     }
 
@@ -354,7 +347,7 @@ ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd)
         *maxfd = server->sock_fd + 1;
     }
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         FD_SET(peer->sock_fd, fds);
         if (peer->sock_fd >= *maxfd) {
             *maxfd = peer->sock_fd + 1;
@@ -374,7 +367,7 @@ ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd)
         return -1;
     }
 
-    TAILQ_FOREACH_SAFE(peer, peer_next, &server->peer_list, next) {
+    QTAILQ_FOREACH_SAFE(peer, &server->peer_list, next, peer_next) {
         /* any message from a peer socket result in a close() */
         debug_log(server, "peer->sock_fd=%d\n", peer->sock_fd);
         if (peer->sock_fd < maxfd && FD_ISSET(peer->sock_fd, fds)) {
@@ -391,7 +384,7 @@ ivshmem_server_search_peer(IvshmemServer *server, long peer_id)
 {
     IvshmemServerPeer *peer;
 
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         if (peer->id == peer_id) {
             return peer;
         }
@@ -407,7 +400,7 @@ ivshmem_server_dump(const IvshmemServer *server)
     unsigned vector;
 
     /* dump peers */
-    TAILQ_FOREACH(peer, &server->peer_list, next) {
+    QTAILQ_FOREACH(peer, &server->peer_list, next) {
         printf("peer_id = %ld\n", peer->id);
 
         for (vector = 0; vector < peer->vectors_count; vector++) {
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index 42736e4..acd17a8 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -28,7 +28,8 @@
 
 #include <limits.h>
 #include <sys/select.h>
-#include <sys/queue.h>
+
+#include "qemu/queue.h"
 
 /**
  * Maximum number of notification vectors supported by the server
@@ -44,13 +45,13 @@
  * unix sockets.
  */
 typedef struct IvshmemServerPeer {
-    TAILQ_ENTRY(IvshmemServerPeer) next;     /**< next in list*/
+    QTAILQ_ENTRY(IvshmemServerPeer) next;    /**< next in list*/
     int sock_fd;                             /**< connected unix sock */
     long id;                                 /**< the id of the peer */
     int vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one fd per vector */
     unsigned vectors_count;                  /**< number of vectors */
 } IvshmemServerPeer;
-TAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
+QTAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
 
 typedef struct IvshmemServerPeerList IvshmemServerPeerList;
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 05/14] contrib/ivshmem-*: switch to QEMU headers
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Reuse parsers from QEMU, C99 boolean.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   12 +----
 contrib/ivshmem-client/ivshmem-client.h |    4 +-
 contrib/ivshmem-client/main.c           |   12 +----
 contrib/ivshmem-server/ivshmem-server.c |   14 +-----
 contrib/ivshmem-server/ivshmem-server.h |    4 +-
 contrib/ivshmem-server/main.c           |   73 +++++--------------------------
 6 files changed, 20 insertions(+), 99 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index ce3a5d2..2ba40a7 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -6,19 +6,11 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "qemu-common.h"
 #include "qemu/queue.h"
 
 #include "ivshmem-client.h"
@@ -149,7 +141,7 @@ handle_server_msg(IvshmemClient *client)
 int
 ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                     ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
-                    int verbose)
+                    bool verbose)
 {
     unsigned i;
 
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index e3b284d..45f2b64 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -78,7 +78,7 @@ struct IvshmemClient {
     ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
     void *notif_arg;                    /**< notification argument */
 
-    int verbose;                        /**< true to enable debug */
+    bool verbose;                       /**< true to enable debug */
 };
 
 /**
@@ -101,7 +101,7 @@ struct IvshmemClient {
  */
 int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                         ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
-                        int verbose);
+                        bool verbose);
 
 /**
  * Connect to the server
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index 778d0f2..f8a7b66 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -6,15 +6,7 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <getopt.h>
+#include "qemu-common.h"
 
 #include "ivshmem-client.h"
 
@@ -22,7 +14,7 @@
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 
 typedef struct IvshmemClientArgs {
-    int verbose;
+    bool verbose;
     char *unix_sock_path;
 } IvshmemClientArgs;
 
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index e58864d..0afa6e8 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -6,23 +6,13 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <fcntl.h>
-
 #include <sys/mman.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/eventfd.h>
 
+#include "qemu-common.h"
 #include "qemu/queue.h"
 
 #include "ivshmem-server.h"
@@ -246,7 +236,7 @@ ivshmem_ftruncate(int fd, unsigned shmsize)
 int
 ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
-                    int verbose)
+                    bool verbose)
 {
     memset(server, 0, sizeof(*server));
 
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index acd17a8..5ccc7af 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -69,7 +69,7 @@ typedef struct IvshmemServer {
     int shm_fd;                      /**< shm file descriptor */
     unsigned n_vectors;              /**< number of vectors */
     long cur_id;                     /**< id to be given to next client */
-    int verbose;                     /**< true in verbose mode */
+    bool verbose;                    /**< true in verbose mode */
     IvshmemServerPeerList peer_list; /**< list of peers */
 } IvshmemServer;
 
@@ -97,7 +97,7 @@ typedef struct IvshmemServer {
 int
 ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
-                    int verbose);
+                    bool verbose);
 
 /**
  * Open the shm, then create and bind to the unix socket
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index a4504c3..f00e6f9 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -6,17 +6,7 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <getopt.h>
+#include "qemu-common.h"
 
 #include "ivshmem-server.h"
 
@@ -30,8 +20,8 @@
 
 /* arguments given by the user */
 typedef struct IvshmemServerArgs {
-    int verbose;
-    int foreground;
+    bool verbose;
+    bool foreground;
     char *pid_file;
     char *unix_socket_path;
     char *shm_path;
@@ -67,59 +57,13 @@ usage(const char *name, int code)
     exit(code);
 }
 
-/* parse the size of shm */
-static int
-parse_size(const char *val_str, size_t *val)
-{
-    char *endptr;
-    unsigned long long tmp;
-
-    errno = 0;
-    tmp = strtoull(val_str, &endptr, 0);
-    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
-        return -1;
-    }
-    if (endptr == val_str) {
-        return -1;
-    }
-    if (endptr[0] == 'K' && endptr[1] == '\0') {
-        tmp *= 1024;
-    } else if (endptr[0] == 'M' && endptr[1] == '\0') {
-        tmp *= 1024 * 1024;
-    } else if (endptr[0] == 'G' && endptr[1] == '\0') {
-        tmp *= 1024 * 1024 * 1024;
-    } else if (endptr[0] != '\0') {
-        return -1;
-    }
-
-    *val = tmp;
-    return 0;
-}
-
-/* parse an unsigned int */
-static int
-parse_uint(const char *val_str, unsigned *val)
-{
-    char *endptr;
-    unsigned long tmp;
-
-    errno = 0;
-    tmp = strtoul(val_str, &endptr, 0);
-    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
-        return -1;
-    }
-    if (endptr == val_str || endptr[0] != '\0') {
-        return -1;
-    }
-    *val = tmp;
-    return 0;
-}
-
 /* parse the program arguments, exit on error */
 static void
 parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 {
     char c;
+    unsigned long long v;
+    Error *errp;
 
     while ((c = getopt(argc, argv,
                        "h"  /* help */
@@ -158,17 +102,20 @@ parse_args(IvshmemServerArgs *args, int argc, char *argv[])
             break;
 
         case 'l': /* shm_size */
-            if (parse_size(optarg, &args->shm_size) < 0) {
+            parse_option_size("shm_size", optarg, &args->shm_size, &errp);
+            if (errp) {
+                error_free(errp);
                 fprintf(stderr, "cannot parse shm size\n");
                 usage(argv[0], 1);
             }
             break;
 
         case 'n': /* n_vectors */
-            if (parse_uint(optarg, &args->n_vectors) < 0) {
+            if (parse_uint_full(optarg, &v, 0) < 0) {
                 fprintf(stderr, "cannot parse n_vectors\n");
                 usage(argv[0], 1);
             }
+            args->n_vectors = v;
             break;
 
         default:
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 05/14] contrib/ivshmem-*: switch to QEMU headers
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Reuse parsers from QEMU, C99 boolean.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   12 +----
 contrib/ivshmem-client/ivshmem-client.h |    4 +-
 contrib/ivshmem-client/main.c           |   12 +----
 contrib/ivshmem-server/ivshmem-server.c |   14 +-----
 contrib/ivshmem-server/ivshmem-server.h |    4 +-
 contrib/ivshmem-server/main.c           |   73 +++++--------------------------
 6 files changed, 20 insertions(+), 99 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index ce3a5d2..2ba40a7 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -6,19 +6,11 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include "qemu-common.h"
 #include "qemu/queue.h"
 
 #include "ivshmem-client.h"
@@ -149,7 +141,7 @@ handle_server_msg(IvshmemClient *client)
 int
 ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                     ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
-                    int verbose)
+                    bool verbose)
 {
     unsigned i;
 
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index e3b284d..45f2b64 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -78,7 +78,7 @@ struct IvshmemClient {
     ivshmem_client_notif_cb_t notif_cb; /**< notification callback */
     void *notif_arg;                    /**< notification argument */
 
-    int verbose;                        /**< true to enable debug */
+    bool verbose;                       /**< true to enable debug */
 };
 
 /**
@@ -101,7 +101,7 @@ struct IvshmemClient {
  */
 int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
                         ivshmem_client_notif_cb_t notif_cb, void *notif_arg,
-                        int verbose);
+                        bool verbose);
 
 /**
  * Connect to the server
diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index 778d0f2..f8a7b66 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -6,15 +6,7 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <getopt.h>
+#include "qemu-common.h"
 
 #include "ivshmem-client.h"
 
@@ -22,7 +14,7 @@
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 
 typedef struct IvshmemClientArgs {
-    int verbose;
+    bool verbose;
     char *unix_sock_path;
 } IvshmemClientArgs;
 
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index e58864d..0afa6e8 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -6,23 +6,13 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <fcntl.h>
-
 #include <sys/mman.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/eventfd.h>
 
+#include "qemu-common.h"
 #include "qemu/queue.h"
 
 #include "ivshmem-server.h"
@@ -246,7 +236,7 @@ ivshmem_ftruncate(int fd, unsigned shmsize)
 int
 ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
-                    int verbose)
+                    bool verbose)
 {
     memset(server, 0, sizeof(*server));
 
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index acd17a8..5ccc7af 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -69,7 +69,7 @@ typedef struct IvshmemServer {
     int shm_fd;                      /**< shm file descriptor */
     unsigned n_vectors;              /**< number of vectors */
     long cur_id;                     /**< id to be given to next client */
-    int verbose;                     /**< true in verbose mode */
+    bool verbose;                    /**< true in verbose mode */
     IvshmemServerPeerList peer_list; /**< list of peers */
 } IvshmemServer;
 
@@ -97,7 +97,7 @@ typedef struct IvshmemServer {
 int
 ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
                     const char *shm_path, size_t shm_size, unsigned n_vectors,
-                    int verbose);
+                    bool verbose);
 
 /**
  * Open the shm, then create and bind to the unix socket
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index a4504c3..f00e6f9 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -6,17 +6,7 @@
  * top-level directory.
  */
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <getopt.h>
+#include "qemu-common.h"
 
 #include "ivshmem-server.h"
 
@@ -30,8 +20,8 @@
 
 /* arguments given by the user */
 typedef struct IvshmemServerArgs {
-    int verbose;
-    int foreground;
+    bool verbose;
+    bool foreground;
     char *pid_file;
     char *unix_socket_path;
     char *shm_path;
@@ -67,59 +57,13 @@ usage(const char *name, int code)
     exit(code);
 }
 
-/* parse the size of shm */
-static int
-parse_size(const char *val_str, size_t *val)
-{
-    char *endptr;
-    unsigned long long tmp;
-
-    errno = 0;
-    tmp = strtoull(val_str, &endptr, 0);
-    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
-        return -1;
-    }
-    if (endptr == val_str) {
-        return -1;
-    }
-    if (endptr[0] == 'K' && endptr[1] == '\0') {
-        tmp *= 1024;
-    } else if (endptr[0] == 'M' && endptr[1] == '\0') {
-        tmp *= 1024 * 1024;
-    } else if (endptr[0] == 'G' && endptr[1] == '\0') {
-        tmp *= 1024 * 1024 * 1024;
-    } else if (endptr[0] != '\0') {
-        return -1;
-    }
-
-    *val = tmp;
-    return 0;
-}
-
-/* parse an unsigned int */
-static int
-parse_uint(const char *val_str, unsigned *val)
-{
-    char *endptr;
-    unsigned long tmp;
-
-    errno = 0;
-    tmp = strtoul(val_str, &endptr, 0);
-    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
-        return -1;
-    }
-    if (endptr == val_str || endptr[0] != '\0') {
-        return -1;
-    }
-    *val = tmp;
-    return 0;
-}
-
 /* parse the program arguments, exit on error */
 static void
 parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 {
     char c;
+    unsigned long long v;
+    Error *errp;
 
     while ((c = getopt(argc, argv,
                        "h"  /* help */
@@ -158,17 +102,20 @@ parse_args(IvshmemServerArgs *args, int argc, char *argv[])
             break;
 
         case 'l': /* shm_size */
-            if (parse_size(optarg, &args->shm_size) < 0) {
+            parse_option_size("shm_size", optarg, &args->shm_size, &errp);
+            if (errp) {
+                error_free(errp);
                 fprintf(stderr, "cannot parse shm size\n");
                 usage(argv[0], 1);
             }
             break;
 
         case 'n': /* n_vectors */
-            if (parse_uint(optarg, &args->n_vectors) < 0) {
+            if (parse_uint_full(optarg, &v, 0) < 0) {
                 fprintf(stderr, "cannot parse n_vectors\n");
                 usage(argv[0], 1);
             }
+            args->n_vectors = v;
             break;
 
         default:
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 06/14] contrib/ivshmem-server: set client sockets as non blocking
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/ivshmem-server.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 0afa6e8..e0d4d1d 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -128,7 +128,8 @@ handle_new_conn(IvshmemServer *server)
 
     /* accept the incoming connection */
     unaddr_len = sizeof(unaddr);
-    newfd = accept(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len);
+    newfd = accept4(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len,
+                    SOCK_NONBLOCK);
     if (newfd < 0) {
         debug_log(server, "cannot accept() %s\n", strerror(errno));
         return -1;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 06/14] contrib/ivshmem-server: set client sockets as non blocking
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/ivshmem-server.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 0afa6e8..e0d4d1d 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -128,7 +128,8 @@ handle_new_conn(IvshmemServer *server)
 
     /* accept the incoming connection */
     unaddr_len = sizeof(unaddr);
-    newfd = accept(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len);
+    newfd = accept4(server->sock_fd, (struct sockaddr *)&unaddr, &unaddr_len,
+                    SOCK_NONBLOCK);
     if (newfd < 0) {
         debug_log(server, "cannot accept() %s\n", strerror(errno));
         return -1;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 07/14] contrib/ivshmem-*: add missing const and static attrs
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/main.c |    6 +++---
 contrib/ivshmem-server/main.c |    8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index f8a7b66..a8e1586 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -15,7 +15,7 @@
 
 typedef struct IvshmemClientArgs {
     bool verbose;
-    char *unix_sock_path;
+    const char *unix_sock_path;
 } IvshmemClientArgs;
 
 /* show usage and exit with given error code */
@@ -129,7 +129,7 @@ handle_stdin_command(IvshmemClient *client)
 
 /* listen on stdin (command line), on unix socket (notifications of new
  * and dead peers), and on eventfd (IRQ request) */
-int
+static int
 poll_events(IvshmemClient *client)
 {
     fd_set fds;
@@ -172,7 +172,7 @@ poll_events(IvshmemClient *client)
 }
 
 /* callback when we receive a notification (just display it) */
-void
+static void
 notification_cb(const IvshmemClient *client, const IvshmemClientPeer *peer,
                 unsigned vect, void *arg)
 {
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index f00e6f9..1966e71 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -22,9 +22,9 @@
 typedef struct IvshmemServerArgs {
     bool verbose;
     bool foreground;
-    char *pid_file;
-    char *unix_socket_path;
-    char *shm_path;
+    const char *pid_file;
+    const char *unix_socket_path;
+    const char *shm_path;
     size_t shm_size;
     unsigned n_vectors;
 } IvshmemServerArgs;
@@ -138,7 +138,7 @@ parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 
 /* wait for events on listening server unix socket and connected client
  * sockets */
-int
+static int
 poll_events(IvshmemServer *server)
 {
     fd_set fds;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 07/14] contrib/ivshmem-*: add missing const and static attrs
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/main.c |    6 +++---
 contrib/ivshmem-server/main.c |    8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/contrib/ivshmem-client/main.c b/contrib/ivshmem-client/main.c
index f8a7b66..a8e1586 100644
--- a/contrib/ivshmem-client/main.c
+++ b/contrib/ivshmem-client/main.c
@@ -15,7 +15,7 @@
 
 typedef struct IvshmemClientArgs {
     bool verbose;
-    char *unix_sock_path;
+    const char *unix_sock_path;
 } IvshmemClientArgs;
 
 /* show usage and exit with given error code */
@@ -129,7 +129,7 @@ handle_stdin_command(IvshmemClient *client)
 
 /* listen on stdin (command line), on unix socket (notifications of new
  * and dead peers), and on eventfd (IRQ request) */
-int
+static int
 poll_events(IvshmemClient *client)
 {
     fd_set fds;
@@ -172,7 +172,7 @@ poll_events(IvshmemClient *client)
 }
 
 /* callback when we receive a notification (just display it) */
-void
+static void
 notification_cb(const IvshmemClient *client, const IvshmemClientPeer *peer,
                 unsigned vect, void *arg)
 {
diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index f00e6f9..1966e71 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -22,9 +22,9 @@
 typedef struct IvshmemServerArgs {
     bool verbose;
     bool foreground;
-    char *pid_file;
-    char *unix_socket_path;
-    char *shm_path;
+    const char *pid_file;
+    const char *unix_socket_path;
+    const char *shm_path;
     size_t shm_size;
     unsigned n_vectors;
 } IvshmemServerArgs;
@@ -138,7 +138,7 @@ parse_args(IvshmemServerArgs *args, int argc, char *argv[])
 
 /* wait for events on listening server unix socket and connected client
  * sockets */
-int
+static int
 poll_events(IvshmemServer *server)
 {
     fd_set fds;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 08/14] contrib/ivshmem-*: plug client and server in QEMU top Makefile
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 Makefile                        |    8 ++++++++
 configure                       |    3 +++
 contrib/ivshmem-client/Makefile |   29 -----------------------------
 contrib/ivshmem-server/Makefile |   29 -----------------------------
 4 files changed, 11 insertions(+), 58 deletions(-)
 delete mode 100644 contrib/ivshmem-client/Makefile
 delete mode 100644 contrib/ivshmem-server/Makefile

diff --git a/Makefile b/Makefile
index b33aaac..0575898 100644
--- a/Makefile
+++ b/Makefile
@@ -283,6 +283,14 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a
 	$(call LINK, $^)
 
+IVSHMEM_CLIENT_OBJS=$(addprefix $(SRC_PATH)/contrib/ivshmem-client/, ivshmem-client.o main.o)
+ivshmem-client$(EXESUF): $(IVSHMEM_CLIENT_OBJS)
+	$(call LINK, $^)
+
+IVSHMEM_SERVER_OBJS=$(addprefix $(SRC_PATH)/contrib/ivshmem-server/, ivshmem-server.o main.o)
+ivshmem-server$(EXESUF): $(IVSHMEM_SERVER_OBJS) libqemuutil.a libqemustub.a
+	$(call LINK, $^)
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
diff --git a/configure b/configure
index 961bf6f..a41a16c 100755
--- a/configure
+++ b/configure
@@ -4125,6 +4125,9 @@ if test "$want_tools" = "yes" ; then
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
     tools="qemu-nbd\$(EXESUF) $tools"
   fi
+  if [ "$kvm" = "yes" ] ; then
+    tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
+  fi
 fi
 if test "$softmmu" = yes ; then
   if test "$virtfs" != no ; then
diff --git a/contrib/ivshmem-client/Makefile b/contrib/ivshmem-client/Makefile
deleted file mode 100644
index eee97c6..0000000
--- a/contrib/ivshmem-client/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 6WIND S.A., 2014
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or
-# (at your option) any later version.  See the COPYING file in the
-# top-level directory.
-
-S ?= $(CURDIR)
-O ?= $(CURDIR)
-
-CFLAGS += -Wall -Wextra -Werror -g
-LDFLAGS +=
-LDLIBS += -lrt
-
-VPATH = $(S)
-PROG = ivshmem-client
-OBJS := $(O)/ivshmem-client.o
-OBJS += $(O)/main.o
-
-$(O)/%.o: %.c
-	$(CC) $(CFLAGS) -o $@ -c $<
-
-$(O)/$(PROG): $(OBJS)
-	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-.PHONY: all
-all: $(O)/$(PROG)
-
-clean:
-	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-server/Makefile b/contrib/ivshmem-server/Makefile
deleted file mode 100644
index 26b4a72..0000000
--- a/contrib/ivshmem-server/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 6WIND S.A., 2014
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or
-# (at your option) any later version.  See the COPYING file in the
-# top-level directory.
-
-S ?= $(CURDIR)
-O ?= $(CURDIR)
-
-CFLAGS += -Wall -Wextra -Werror -g
-LDFLAGS +=
-LDLIBS += -lrt
-
-VPATH = $(S)
-PROG = ivshmem-server
-OBJS := $(O)/ivshmem-server.o
-OBJS += $(O)/main.o
-
-$(O)/%.o: %.c
-	$(CC) $(CFLAGS) -o $@ -c $<
-
-$(O)/$(PROG): $(OBJS)
-	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-.PHONY: all
-all: $(O)/$(PROG)
-
-clean:
-	rm -f $(OBJS) $(O)/$(PROG)
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 08/14] contrib/ivshmem-*: plug client and server in QEMU top Makefile
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 Makefile                        |    8 ++++++++
 configure                       |    3 +++
 contrib/ivshmem-client/Makefile |   29 -----------------------------
 contrib/ivshmem-server/Makefile |   29 -----------------------------
 4 files changed, 11 insertions(+), 58 deletions(-)
 delete mode 100644 contrib/ivshmem-client/Makefile
 delete mode 100644 contrib/ivshmem-server/Makefile

diff --git a/Makefile b/Makefile
index b33aaac..0575898 100644
--- a/Makefile
+++ b/Makefile
@@ -283,6 +283,14 @@ $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
 qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a
 	$(call LINK, $^)
 
+IVSHMEM_CLIENT_OBJS=$(addprefix $(SRC_PATH)/contrib/ivshmem-client/, ivshmem-client.o main.o)
+ivshmem-client$(EXESUF): $(IVSHMEM_CLIENT_OBJS)
+	$(call LINK, $^)
+
+IVSHMEM_SERVER_OBJS=$(addprefix $(SRC_PATH)/contrib/ivshmem-server/, ivshmem-server.o main.o)
+ivshmem-server$(EXESUF): $(IVSHMEM_SERVER_OBJS) libqemuutil.a libqemustub.a
+	$(call LINK, $^)
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
diff --git a/configure b/configure
index 961bf6f..a41a16c 100755
--- a/configure
+++ b/configure
@@ -4125,6 +4125,9 @@ if test "$want_tools" = "yes" ; then
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
     tools="qemu-nbd\$(EXESUF) $tools"
   fi
+  if [ "$kvm" = "yes" ] ; then
+    tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
+  fi
 fi
 if test "$softmmu" = yes ; then
   if test "$virtfs" != no ; then
diff --git a/contrib/ivshmem-client/Makefile b/contrib/ivshmem-client/Makefile
deleted file mode 100644
index eee97c6..0000000
--- a/contrib/ivshmem-client/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 6WIND S.A., 2014
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or
-# (at your option) any later version.  See the COPYING file in the
-# top-level directory.
-
-S ?= $(CURDIR)
-O ?= $(CURDIR)
-
-CFLAGS += -Wall -Wextra -Werror -g
-LDFLAGS +=
-LDLIBS += -lrt
-
-VPATH = $(S)
-PROG = ivshmem-client
-OBJS := $(O)/ivshmem-client.o
-OBJS += $(O)/main.o
-
-$(O)/%.o: %.c
-	$(CC) $(CFLAGS) -o $@ -c $<
-
-$(O)/$(PROG): $(OBJS)
-	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-.PHONY: all
-all: $(O)/$(PROG)
-
-clean:
-	rm -f $(OBJS) $(O)/$(PROG)
diff --git a/contrib/ivshmem-server/Makefile b/contrib/ivshmem-server/Makefile
deleted file mode 100644
index 26b4a72..0000000
--- a/contrib/ivshmem-server/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 6WIND S.A., 2014
-#
-# This work is licensed under the terms of the GNU GPL, version 2 or
-# (at your option) any later version.  See the COPYING file in the
-# top-level directory.
-
-S ?= $(CURDIR)
-O ?= $(CURDIR)
-
-CFLAGS += -Wall -Wextra -Werror -g
-LDFLAGS +=
-LDLIBS += -lrt
-
-VPATH = $(S)
-PROG = ivshmem-server
-OBJS := $(O)/ivshmem-server.o
-OBJS += $(O)/main.o
-
-$(O)/%.o: %.c
-	$(CC) $(CFLAGS) -o $@ -c $<
-
-$(O)/$(PROG): $(OBJS)
-	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-.PHONY: all
-all: $(O)/$(PROG)
-
-clean:
-	rm -f $(OBJS) $(O)/$(PROG)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 09/14] contrib/ivshmem-*: switch to g_malloc0/g_free
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |    9 ++-------
 contrib/ivshmem-server/ivshmem-server.c |   12 ++----------
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 2ba40a7..a08f4d9 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -82,7 +82,7 @@ free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
         close(peer->vectors[vector]);
     }
 
-    free(peer);
+    g_free(peer);
 }
 
 /* handle message coming from server (new peer, new vectors) */
@@ -116,12 +116,7 @@ handle_server_msg(IvshmemClient *client)
 
     /* new peer */
     if (peer == NULL) {
-        peer = malloc(sizeof(*peer));
-        if (peer == NULL) {
-            debug_log(client, "cannot allocate new peer\n");
-            return -1;
-        }
-        memset(peer, 0, sizeof(*peer));
+        peer = g_malloc0(sizeof(*peer));
         peer->id = peer_id;
         peer->vectors_count = 0;
         QTAILQ_INSERT_TAIL(&client->peer_list, peer, next);
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index e0d4d1d..15d468c 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -90,7 +90,7 @@ free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
         close(peer->vectors[vector]);
     }
 
-    free(peer);
+    g_free(peer);
 }
 
 /* send the peer id and the shm_fd just after a new client connection */
@@ -138,15 +138,7 @@ handle_new_conn(IvshmemServer *server)
     debug_log(server, "accept()=%d\n", newfd);
 
     /* allocate new structure for this peer */
-    peer = malloc(sizeof(*peer));
-    if (peer == NULL) {
-        debug_log(server, "cannot allocate new peer\n");
-        close(newfd);
-        return -1;
-    }
-
-    /* initialize the peer struct, one eventfd per vector */
-    memset(peer, 0, sizeof(*peer));
+    peer = g_malloc0(sizeof(*peer));
     peer->sock_fd = newfd;
 
     /* get an unused peer id */
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 09/14] contrib/ivshmem-*: switch to g_malloc0/g_free
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |    9 ++-------
 contrib/ivshmem-server/ivshmem-server.c |   12 ++----------
 2 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index 2ba40a7..a08f4d9 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -82,7 +82,7 @@ free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
         close(peer->vectors[vector]);
     }
 
-    free(peer);
+    g_free(peer);
 }
 
 /* handle message coming from server (new peer, new vectors) */
@@ -116,12 +116,7 @@ handle_server_msg(IvshmemClient *client)
 
     /* new peer */
     if (peer == NULL) {
-        peer = malloc(sizeof(*peer));
-        if (peer == NULL) {
-            debug_log(client, "cannot allocate new peer\n");
-            return -1;
-        }
-        memset(peer, 0, sizeof(*peer));
+        peer = g_malloc0(sizeof(*peer));
         peer->id = peer_id;
         peer->vectors_count = 0;
         QTAILQ_INSERT_TAIL(&client->peer_list, peer, next);
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index e0d4d1d..15d468c 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -90,7 +90,7 @@ free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
         close(peer->vectors[vector]);
     }
 
-    free(peer);
+    g_free(peer);
 }
 
 /* send the peer id and the shm_fd just after a new client connection */
@@ -138,15 +138,7 @@ handle_new_conn(IvshmemServer *server)
     debug_log(server, "accept()=%d\n", newfd);
 
     /* allocate new structure for this peer */
-    peer = malloc(sizeof(*peer));
-    if (peer == NULL) {
-        debug_log(server, "cannot allocate new peer\n");
-        close(newfd);
-        return -1;
-    }
-
-    /* initialize the peer struct, one eventfd per vector */
-    memset(peer, 0, sizeof(*peer));
+    peer = g_malloc0(sizeof(*peer));
     peer->sock_fd = newfd;
 
     /* get an unused peer id */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 10/14] contrib/ivshmem-server: fix mem leak on error
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/ivshmem-server.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 15d468c..4732dab 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -190,8 +190,8 @@ fail:
     while (i--) {
         close(peer->vectors[i]);
     }
-    peer->sock_fd = -1;
     close(newfd);
+    g_free(peer);
     return -1;
 }
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 10/14] contrib/ivshmem-server: fix mem leak on error
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/ivshmem-server.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 15d468c..4732dab 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -190,8 +190,8 @@ fail:
     while (i--) {
         close(peer->vectors[i]);
     }
-    peer->sock_fd = -1;
     close(newfd);
+    g_free(peer);
     return -1;
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 11/14] contrib/ivshmem-*: rework error handling
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Following Gonglei comments, rework error handling using goto.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   17 ++++++++---------
 contrib/ivshmem-server/ivshmem-server.c |   19 ++++++++++---------
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index a08f4d9..e9a19ff 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -180,18 +180,14 @@ ivshmem_client_connect(IvshmemClient *client)
     if (connect(client->sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
         debug_log(client, "cannot connect to %s: %s\n", sun.sun_path,
                   strerror(errno));
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
 
     /* first, we expect our index + a fd == -1 */
     if (read_one_msg(client, &client->local.id, &fd) < 0 ||
         client->local.id < 0 || fd != -1) {
         debug_log(client, "cannot read from server\n");
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
     debug_log(client, "our_id=%ld\n", client->local.id);
 
@@ -200,13 +196,16 @@ ivshmem_client_connect(IvshmemClient *client)
     if (read_one_msg(client, &tmp, &fd) < 0 ||
         tmp != -1 || fd < 0) {
         debug_log(client, "cannot read from server (2)\n");
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
     debug_log(client, "shm_fd=%d\n", fd);
 
     return 0;
+
+err_close:
+    close(client->sock_fd);
+    client->sock_fd = -1;
+    return -1;
 }
 
 /* close connection to the server, and free all peer structures */
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 4732dab..f441da7 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -264,7 +264,7 @@ ivshmem_server_start(IvshmemServer *server)
     if (ivshmem_ftruncate(shm_fd, server->shm_size) < 0) {
         fprintf(stderr, "ftruncate(%s) failed: %s\n", server->shm_path,
                 strerror(errno));
-        return -1;
+        goto err_close_shm;
     }
 
     debug_log(server, "create & bind socket %s\n", server->unix_sock_path);
@@ -273,8 +273,7 @@ ivshmem_server_start(IvshmemServer *server)
     sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (sock_fd < 0) {
         debug_log(server, "cannot create socket: %s\n", strerror(errno));
-        close(shm_fd);
-        return -1;
+        goto err_close_shm;
     }
 
     sun.sun_family = AF_UNIX;
@@ -283,22 +282,24 @@ ivshmem_server_start(IvshmemServer *server)
     if (bind(sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
         debug_log(server, "cannot connect to %s: %s\n", sun.sun_path,
                   strerror(errno));
-        close(sock_fd);
-        close(shm_fd);
-        return -1;
+        goto err_close_sock;
     }
 
     if (listen(sock_fd, IVSHMEM_SERVER_LISTEN_BACKLOG) < 0) {
         debug_log(server, "listen() failed: %s\n", strerror(errno));
-        close(sock_fd);
-        close(shm_fd);
-        return -1;
+        goto err_close_sock;
     }
 
     server->sock_fd = sock_fd;
     server->shm_fd = shm_fd;
 
     return 0;
+
+err_close_sock:
+    close(sock_fd);
+err_close_shm:
+    close(shm_fd);
+    return -1;
 }
 
 /* close connections to clients, the unix socket and the shm fd */
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 11/14] contrib/ivshmem-*: rework error handling
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Following Gonglei comments, rework error handling using goto.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   17 ++++++++---------
 contrib/ivshmem-server/ivshmem-server.c |   19 ++++++++++---------
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index a08f4d9..e9a19ff 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -180,18 +180,14 @@ ivshmem_client_connect(IvshmemClient *client)
     if (connect(client->sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
         debug_log(client, "cannot connect to %s: %s\n", sun.sun_path,
                   strerror(errno));
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
 
     /* first, we expect our index + a fd == -1 */
     if (read_one_msg(client, &client->local.id, &fd) < 0 ||
         client->local.id < 0 || fd != -1) {
         debug_log(client, "cannot read from server\n");
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
     debug_log(client, "our_id=%ld\n", client->local.id);
 
@@ -200,13 +196,16 @@ ivshmem_client_connect(IvshmemClient *client)
     if (read_one_msg(client, &tmp, &fd) < 0 ||
         tmp != -1 || fd < 0) {
         debug_log(client, "cannot read from server (2)\n");
-        close(client->sock_fd);
-        client->sock_fd = -1;
-        return -1;
+        goto err_close;
     }
     debug_log(client, "shm_fd=%d\n", fd);
 
     return 0;
+
+err_close:
+    close(client->sock_fd);
+    client->sock_fd = -1;
+    return -1;
 }
 
 /* close connection to the server, and free all peer structures */
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index 4732dab..f441da7 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -264,7 +264,7 @@ ivshmem_server_start(IvshmemServer *server)
     if (ivshmem_ftruncate(shm_fd, server->shm_size) < 0) {
         fprintf(stderr, "ftruncate(%s) failed: %s\n", server->shm_path,
                 strerror(errno));
-        return -1;
+        goto err_close_shm;
     }
 
     debug_log(server, "create & bind socket %s\n", server->unix_sock_path);
@@ -273,8 +273,7 @@ ivshmem_server_start(IvshmemServer *server)
     sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (sock_fd < 0) {
         debug_log(server, "cannot create socket: %s\n", strerror(errno));
-        close(shm_fd);
-        return -1;
+        goto err_close_shm;
     }
 
     sun.sun_family = AF_UNIX;
@@ -283,22 +282,24 @@ ivshmem_server_start(IvshmemServer *server)
     if (bind(sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
         debug_log(server, "cannot connect to %s: %s\n", sun.sun_path,
                   strerror(errno));
-        close(sock_fd);
-        close(shm_fd);
-        return -1;
+        goto err_close_sock;
     }
 
     if (listen(sock_fd, IVSHMEM_SERVER_LISTEN_BACKLOG) < 0) {
         debug_log(server, "listen() failed: %s\n", strerror(errno));
-        close(sock_fd);
-        close(shm_fd);
-        return -1;
+        goto err_close_sock;
     }
 
     server->sock_fd = sock_fd;
     server->shm_fd = shm_fd;
 
     return 0;
+
+err_close_sock:
+    close(sock_fd);
+err_close_shm:
+    close(shm_fd);
+    return -1;
 }
 
 /* close connections to clients, the unix socket and the shm fd */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 12/14] contrib/ivshmem-*: various fixes
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

More fixes following Gonglei comments:
- add a missing \n in a debug message.
- add an explicit initialisation of sock_fd.
- fix a check on vector index.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index e9a19ff..ad210c8 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -105,7 +105,7 @@ handle_server_msg(IvshmemClient *client)
     if (fd == -1) {
 
         if (peer == NULL || peer == &client->local) {
-            debug_log(client, "receive delete for invalid peer %ld", peer_id);
+            debug_log(client, "receive delete for invalid peer %ld\n", peer_id);
             return -1;
         }
 
@@ -155,6 +155,7 @@ ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
     client->notif_cb = notif_cb;
     client->notif_arg = notif_arg;
     client->verbose = verbose;
+    client->sock_fd = -1;
 
     return 0;
 }
@@ -309,7 +310,7 @@ ivshmem_client_notify(const IvshmemClient *client,
     uint64_t kick;
     int fd;
 
-    if (vector > peer->vectors_count) {
+    if (vector >= peer->vectors_count) {
         debug_log(client, "invalid vector %u on peer %ld\n", vector, peer->id);
         return -1;
     }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 12/14] contrib/ivshmem-*: various fixes
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

More fixes following Gonglei comments:
- add a missing \n in a debug message.
- add an explicit initialisation of sock_fd.
- fix a check on vector index.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index e9a19ff..ad210c8 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -105,7 +105,7 @@ handle_server_msg(IvshmemClient *client)
     if (fd == -1) {
 
         if (peer == NULL || peer == &client->local) {
-            debug_log(client, "receive delete for invalid peer %ld", peer_id);
+            debug_log(client, "receive delete for invalid peer %ld\n", peer_id);
             return -1;
         }
 
@@ -155,6 +155,7 @@ ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
     client->notif_cb = notif_cb;
     client->notif_arg = notif_arg;
     client->verbose = verbose;
+    client->sock_fd = -1;
 
     return 0;
 }
@@ -309,7 +310,7 @@ ivshmem_client_notify(const IvshmemClient *client,
     uint64_t kick;
     int fd;
 
-    if (vector > peer->vectors_count) {
+    if (vector >= peer->vectors_count) {
         debug_log(client, "invalid vector %u on peer %ld\n", vector, peer->id);
         return -1;
     }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 13/14] contrib/ivshmem-server: align server default parameter values
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

ivshmem server should use the same default values as hw/misc/ivshmem.
Update accordingly.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/main.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index 1966e71..8792fc8 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -15,8 +15,8 @@
 #define DEFAULT_PID_FILE       "/var/run/ivshmem-server.pid"
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 #define DEFAULT_SHM_PATH       "ivshmem"
-#define DEFAULT_SHM_SIZE       (1024*1024)
-#define DEFAULT_N_VECTORS      16
+#define DEFAULT_SHM_SIZE       (4*1024*1024)
+#define DEFAULT_N_VECTORS      1
 
 /* arguments given by the user */
 typedef struct IvshmemServerArgs {
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 13/14] contrib/ivshmem-server: align server default parameter values
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

ivshmem server should use the same default values as hw/misc/ivshmem.
Update accordingly.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-server/main.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/contrib/ivshmem-server/main.c b/contrib/ivshmem-server/main.c
index 1966e71..8792fc8 100644
--- a/contrib/ivshmem-server/main.c
+++ b/contrib/ivshmem-server/main.c
@@ -15,8 +15,8 @@
 #define DEFAULT_PID_FILE       "/var/run/ivshmem-server.pid"
 #define DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
 #define DEFAULT_SHM_PATH       "ivshmem"
-#define DEFAULT_SHM_SIZE       (1024*1024)
-#define DEFAULT_N_VECTORS      16
+#define DEFAULT_SHM_SIZE       (4*1024*1024)
+#define DEFAULT_N_VECTORS      1
 
 /* arguments given by the user */
 typedef struct IvshmemServerArgs {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v4 14/14] ivshmem: add check on protocol version in QEMU
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 15:25   ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, eblake, cam,
	armbru, stefanha, arei.gonglei

Send a protocol version as the first message from server, clients must close
communication if they don't support this protocol version.
Older QEMUs should be fine with this change in the protocol since they overrides
their own vm_id on reception of an id associated to no eventfd.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   14 +++++++---
 contrib/ivshmem-client/ivshmem-client.h |    1 +
 contrib/ivshmem-server/ivshmem-server.c |    7 +++++
 contrib/ivshmem-server/ivshmem-server.h |    1 +
 docs/specs/ivshmem_device_spec.txt      |    9 ++++---
 hw/misc/ivshmem.c                       |   43 ++++++++++++++++++++++++-------
 include/hw/misc/ivshmem.h               |   17 ++++++++++++
 7 files changed, 77 insertions(+), 15 deletions(-)
 create mode 100644 include/hw/misc/ivshmem.h

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index ad210c8..0c4e016 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -184,10 +184,18 @@ ivshmem_client_connect(IvshmemClient *client)
         goto err_close;
     }
 
-    /* first, we expect our index + a fd == -1 */
+    /* first, we expect a protocol version */
+    if (read_one_msg(client, &tmp, &fd) < 0 ||
+        (tmp != IVSHMEM_PROTOCOL_VERSION) || fd != -1) {
+        debug_log(client, "cannot read from server\n");
+        goto err_close;
+    }
+    debug_log(client, "our_id=%ld\n", client->local.id);
+
+    /* then, we expect our index + a fd == -1 */
     if (read_one_msg(client, &client->local.id, &fd) < 0 ||
         client->local.id < 0 || fd != -1) {
-        debug_log(client, "cannot read from server\n");
+        debug_log(client, "cannot read from server (2)\n");
         goto err_close;
     }
     debug_log(client, "our_id=%ld\n", client->local.id);
@@ -196,7 +204,7 @@ ivshmem_client_connect(IvshmemClient *client)
      * is not used */
     if (read_one_msg(client, &tmp, &fd) < 0 ||
         tmp != -1 || fd < 0) {
-        debug_log(client, "cannot read from server (2)\n");
+        debug_log(client, "cannot read from server (3)\n");
         goto err_close;
     }
     debug_log(client, "shm_fd=%d\n", fd);
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index 45f2b64..8d6ab35 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -23,6 +23,7 @@
 #include <sys/select.h>
 
 #include "qemu/queue.h"
+#include "hw/misc/ivshmem.h"
 
 /**
  * Maximum number of notification vectors supported by the client
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index f441da7..670c58c 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -99,6 +99,13 @@ send_initial_info(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     int ret;
 
+    /* send our protool version first */
+    ret = send_one_msg(peer->sock_fd, IVSHMEM_PROTOCOL_VERSION, -1);
+    if (ret < 0) {
+        debug_log(server, "cannot send version: %s\n", strerror(errno));
+        return -1;
+    }
+
     /* send the peer id to the client */
     ret = send_one_msg(peer->sock_fd, peer->id, -1);
     if (ret < 0) {
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index 5ccc7af..e76e4fe 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -30,6 +30,7 @@
 #include <sys/select.h>
 
 #include "qemu/queue.h"
+#include "hw/misc/ivshmem.h"
 
 /**
  * Maximum number of notification vectors supported by the server
diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt
index f5f2b95..bae87de 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -64,6 +64,8 @@ It creates a shared memory object then waits for clients to connect on an unix
 socket.
 
 For each client (QEMU processes) that connects to the server:
+- the server sends a protocol version, if client does not support it, the client
+  closes the communication,
 - the server assigns an ID for this client and sends this ID to him as the first
   message,
 - the server sends a fd to the shared memory object to this client,
@@ -86,9 +88,10 @@ been provided in qemu.git/contrib/ivshmem-client for debug.
 
 *QEMU as an ivshmem client*
 
-At initialisation, when creating the ivshmem device, QEMU gets its ID from the
-server then make it available through BAR0 IVPosition register for the VM to use
-(see 'PCI device registers' subsection).
+At initialisation, when creating the ivshmem device, QEMU first receives a
+protocol version and closes communication with server if it does not match.
+Then, QEMU gets its ID from the server then make it available through BAR0
+IVPosition register for the VM to use (see 'PCI device registers' subsection).
 QEMU then uses the fd to the shared memory to map it to BAR2.
 eventfds for all other clients received from the server are stored to implement
 BAR0 Doorbell register (see 'PCI device registers' subsection).
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index bd9d718..305dab8 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -26,6 +26,8 @@
 #include "qemu/event_notifier.h"
 #include "sysemu/char.h"
 
+#include "hw/misc/ivshmem.h"
+
 #include <sys/mman.h>
 #include <sys/types.h>
 
@@ -528,6 +530,36 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
     }
 }
 
+static void ivshmem_check_version(void *opaque, const uint8_t * buf, int flags)
+{
+    IVShmemState *s = opaque;
+    PCIDevice *dev = PCI_DEVICE(s);
+    int tmp;
+    long version;
+
+    memcpy(&version, buf, sizeof(long));
+    tmp = qemu_chr_fe_get_msgfd(s->server_chr);
+    if (tmp != -1 || version != IVSHMEM_PROTOCOL_VERSION) {
+        fprintf(stderr, "incompatible version, you are connecting to a ivhsmem-"
+                "server using a different protocol please check your setup\n");
+        qemu_chr_delete(s->server_chr);
+        s->server_chr = NULL;
+        return;
+    }
+
+    IVSHMEM_DPRINTF("version check ok, finish init and switch to real chardev "
+                    "handler\n");
+
+    pci_register_bar(dev, 2, s->ivshmem_attr, &s->bar);
+
+    /* allocate/initialize space for interrupt handling */
+    s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
+    s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
+
+    qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
+                          ivshmem_event, s);
+}
+
 /* Select the MSI-X vectors used by device.
  * ivshmem maps events to vectors statically, so
  * we just enable all vectors on init and after reset. */
@@ -735,15 +767,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
         s->nb_peers = 16;
         s->vm_id = -1;
 
-        /* allocate/initialize space for interrupt handling */
-        s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
-
-        pci_register_bar(dev, 2, s->ivshmem_attr, &s->bar);
-
-        s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
-
-        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
-                     ivshmem_event, s);
+        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
+                              ivshmem_check_version, ivshmem_event, s);
     } else {
         /* just map the file immediately, we're not using a server */
         int fd;
diff --git a/include/hw/misc/ivshmem.h b/include/hw/misc/ivshmem.h
new file mode 100644
index 0000000..22c9f1f
--- /dev/null
+++ b/include/hw/misc/ivshmem.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_H_
+#define _IVSHMEM_H_
+
+/**
+ * Protocol version
+ */
+#define IVSHMEM_PROTOCOL_VERSION 0x0
+
+#endif
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [Qemu-devel] [PATCH v4 14/14] ivshmem: add check on protocol version in QEMU
@ 2014-09-02 15:25   ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-02 15:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

Send a protocol version as the first message from server, clients must close
communication if they don't support this protocol version.
Older QEMUs should be fine with this change in the protocol since they overrides
their own vm_id on reception of an id associated to no eventfd.

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 contrib/ivshmem-client/ivshmem-client.c |   14 +++++++---
 contrib/ivshmem-client/ivshmem-client.h |    1 +
 contrib/ivshmem-server/ivshmem-server.c |    7 +++++
 contrib/ivshmem-server/ivshmem-server.h |    1 +
 docs/specs/ivshmem_device_spec.txt      |    9 ++++---
 hw/misc/ivshmem.c                       |   43 ++++++++++++++++++++++++-------
 include/hw/misc/ivshmem.h               |   17 ++++++++++++
 7 files changed, 77 insertions(+), 15 deletions(-)
 create mode 100644 include/hw/misc/ivshmem.h

diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c
index ad210c8..0c4e016 100644
--- a/contrib/ivshmem-client/ivshmem-client.c
+++ b/contrib/ivshmem-client/ivshmem-client.c
@@ -184,10 +184,18 @@ ivshmem_client_connect(IvshmemClient *client)
         goto err_close;
     }
 
-    /* first, we expect our index + a fd == -1 */
+    /* first, we expect a protocol version */
+    if (read_one_msg(client, &tmp, &fd) < 0 ||
+        (tmp != IVSHMEM_PROTOCOL_VERSION) || fd != -1) {
+        debug_log(client, "cannot read from server\n");
+        goto err_close;
+    }
+    debug_log(client, "our_id=%ld\n", client->local.id);
+
+    /* then, we expect our index + a fd == -1 */
     if (read_one_msg(client, &client->local.id, &fd) < 0 ||
         client->local.id < 0 || fd != -1) {
-        debug_log(client, "cannot read from server\n");
+        debug_log(client, "cannot read from server (2)\n");
         goto err_close;
     }
     debug_log(client, "our_id=%ld\n", client->local.id);
@@ -196,7 +204,7 @@ ivshmem_client_connect(IvshmemClient *client)
      * is not used */
     if (read_one_msg(client, &tmp, &fd) < 0 ||
         tmp != -1 || fd < 0) {
-        debug_log(client, "cannot read from server (2)\n");
+        debug_log(client, "cannot read from server (3)\n");
         goto err_close;
     }
     debug_log(client, "shm_fd=%d\n", fd);
diff --git a/contrib/ivshmem-client/ivshmem-client.h b/contrib/ivshmem-client/ivshmem-client.h
index 45f2b64..8d6ab35 100644
--- a/contrib/ivshmem-client/ivshmem-client.h
+++ b/contrib/ivshmem-client/ivshmem-client.h
@@ -23,6 +23,7 @@
 #include <sys/select.h>
 
 #include "qemu/queue.h"
+#include "hw/misc/ivshmem.h"
 
 /**
  * Maximum number of notification vectors supported by the client
diff --git a/contrib/ivshmem-server/ivshmem-server.c b/contrib/ivshmem-server/ivshmem-server.c
index f441da7..670c58c 100644
--- a/contrib/ivshmem-server/ivshmem-server.c
+++ b/contrib/ivshmem-server/ivshmem-server.c
@@ -99,6 +99,13 @@ send_initial_info(IvshmemServer *server, IvshmemServerPeer *peer)
 {
     int ret;
 
+    /* send our protool version first */
+    ret = send_one_msg(peer->sock_fd, IVSHMEM_PROTOCOL_VERSION, -1);
+    if (ret < 0) {
+        debug_log(server, "cannot send version: %s\n", strerror(errno));
+        return -1;
+    }
+
     /* send the peer id to the client */
     ret = send_one_msg(peer->sock_fd, peer->id, -1);
     if (ret < 0) {
diff --git a/contrib/ivshmem-server/ivshmem-server.h b/contrib/ivshmem-server/ivshmem-server.h
index 5ccc7af..e76e4fe 100644
--- a/contrib/ivshmem-server/ivshmem-server.h
+++ b/contrib/ivshmem-server/ivshmem-server.h
@@ -30,6 +30,7 @@
 #include <sys/select.h>
 
 #include "qemu/queue.h"
+#include "hw/misc/ivshmem.h"
 
 /**
  * Maximum number of notification vectors supported by the server
diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt
index f5f2b95..bae87de 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -64,6 +64,8 @@ It creates a shared memory object then waits for clients to connect on an unix
 socket.
 
 For each client (QEMU processes) that connects to the server:
+- the server sends a protocol version, if client does not support it, the client
+  closes the communication,
 - the server assigns an ID for this client and sends this ID to him as the first
   message,
 - the server sends a fd to the shared memory object to this client,
@@ -86,9 +88,10 @@ been provided in qemu.git/contrib/ivshmem-client for debug.
 
 *QEMU as an ivshmem client*
 
-At initialisation, when creating the ivshmem device, QEMU gets its ID from the
-server then make it available through BAR0 IVPosition register for the VM to use
-(see 'PCI device registers' subsection).
+At initialisation, when creating the ivshmem device, QEMU first receives a
+protocol version and closes communication with server if it does not match.
+Then, QEMU gets its ID from the server then make it available through BAR0
+IVPosition register for the VM to use (see 'PCI device registers' subsection).
 QEMU then uses the fd to the shared memory to map it to BAR2.
 eventfds for all other clients received from the server are stored to implement
 BAR0 Doorbell register (see 'PCI device registers' subsection).
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index bd9d718..305dab8 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -26,6 +26,8 @@
 #include "qemu/event_notifier.h"
 #include "sysemu/char.h"
 
+#include "hw/misc/ivshmem.h"
+
 #include <sys/mman.h>
 #include <sys/types.h>
 
@@ -528,6 +530,36 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
     }
 }
 
+static void ivshmem_check_version(void *opaque, const uint8_t * buf, int flags)
+{
+    IVShmemState *s = opaque;
+    PCIDevice *dev = PCI_DEVICE(s);
+    int tmp;
+    long version;
+
+    memcpy(&version, buf, sizeof(long));
+    tmp = qemu_chr_fe_get_msgfd(s->server_chr);
+    if (tmp != -1 || version != IVSHMEM_PROTOCOL_VERSION) {
+        fprintf(stderr, "incompatible version, you are connecting to a ivhsmem-"
+                "server using a different protocol please check your setup\n");
+        qemu_chr_delete(s->server_chr);
+        s->server_chr = NULL;
+        return;
+    }
+
+    IVSHMEM_DPRINTF("version check ok, finish init and switch to real chardev "
+                    "handler\n");
+
+    pci_register_bar(dev, 2, s->ivshmem_attr, &s->bar);
+
+    /* allocate/initialize space for interrupt handling */
+    s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
+    s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
+
+    qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
+                          ivshmem_event, s);
+}
+
 /* Select the MSI-X vectors used by device.
  * ivshmem maps events to vectors statically, so
  * we just enable all vectors on init and after reset. */
@@ -735,15 +767,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
         s->nb_peers = 16;
         s->vm_id = -1;
 
-        /* allocate/initialize space for interrupt handling */
-        s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
-
-        pci_register_bar(dev, 2, s->ivshmem_attr, &s->bar);
-
-        s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
-
-        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read,
-                     ivshmem_event, s);
+        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
+                              ivshmem_check_version, ivshmem_event, s);
     } else {
         /* just map the file immediately, we're not using a server */
         int fd;
diff --git a/include/hw/misc/ivshmem.h b/include/hw/misc/ivshmem.h
new file mode 100644
index 0000000..22c9f1f
--- /dev/null
+++ b/include/hw/misc/ivshmem.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 6WIND S.A., 2014
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _IVSHMEM_H_
+#define _IVSHMEM_H_
+
+/**
+ * Protocol version
+ */
+#define IVSHMEM_PROTOCOL_VERSION 0x0
+
+#endif
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 01/14] contrib: add ivshmem client and server
  2014-09-02 15:25   ` [Qemu-devel] " David Marchand
@ 2014-09-02 20:20     ` Eric Blake
  -1 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:20 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, cam, armbru,
	stefanha, arei.gonglei, Olivier Matz

[-- Attachment #1: Type: text/plain, Size: 1395 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> When using ivshmem devices, notifications between guests can be sent as
> interrupts using a ivshmem-server (typical use described in documentation).
> The client is provided as a debug tool.
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> ---

> +/* parse the size of shm */
> +static int
> +parse_size(const char *val_str, size_t *val)
> +{
> +    char *endptr;
> +    unsigned long long tmp;
> +
> +    errno = 0;
> +    tmp = strtoull(val_str, &endptr, 0);
> +    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
> +        return -1;
> +    }

This is overly complex; usually, this is just done as:

if (errno)
    return -1;

> +/* parse an unsigned int */
> +static int
> +parse_uint(const char *val_str, unsigned *val)
> +{
> +    char *endptr;
> +    unsigned long tmp;
> +
> +    errno = 0;
> +    tmp = strtoul(val_str, &endptr, 0);
> +    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
> +        return -1;
> +    }

and again

> +    if (endptr == val_str || endptr[0] != '\0') {
> +        return -1;
> +    }
> +    *val = tmp;
> +    return 0;
> +}

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 01/14] contrib: add ivshmem client and server
@ 2014-09-02 20:20     ` Eric Blake
  0 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:20 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: Olivier Matz, kvm, stefanha, claudio.fontana, armbru,
	arei.gonglei, pbonzini, jani.kokkonen, cam

[-- Attachment #1: Type: text/plain, Size: 1395 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> When using ivshmem devices, notifications between guests can be sent as
> interrupts using a ivshmem-server (typical use described in documentation).
> The client is provided as a debug tool.
> 
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> ---

> +/* parse the size of shm */
> +static int
> +parse_size(const char *val_str, size_t *val)
> +{
> +    char *endptr;
> +    unsigned long long tmp;
> +
> +    errno = 0;
> +    tmp = strtoull(val_str, &endptr, 0);
> +    if ((errno == ERANGE && tmp == ULLONG_MAX) || (errno != 0 && tmp == 0)) {
> +        return -1;
> +    }

This is overly complex; usually, this is just done as:

if (errno)
    return -1;

> +/* parse an unsigned int */
> +static int
> +parse_uint(const char *val_str, unsigned *val)
> +{
> +    char *endptr;
> +    unsigned long tmp;
> +
> +    errno = 0;
> +    tmp = strtoul(val_str, &endptr, 0);
> +    if ((errno == ERANGE && tmp == ULONG_MAX) || (errno != 0 && tmp == 0)) {
> +        return -1;
> +    }

and again

> +    if (endptr == val_str || endptr[0] != '\0') {
> +        return -1;
> +    }
> +    *val = tmp;
> +    return 0;
> +}

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 02/14] docs: update ivshmem device spec
  2014-09-02 15:25   ` [Qemu-devel] " David Marchand
@ 2014-09-02 20:24     ` Eric Blake
  -1 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:24 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, cam, armbru,
	stefanha, arei.gonglei

[-- Attachment #1: Type: text/plain, Size: 1687 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Add some notes on the parts needed to use ivshmem devices: more specifically,
> explain the purpose of an ivshmem server and the basic concept to use the
> ivshmem devices in guests.
> Move some parts of the documentation and re-organise it.
> 
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
> ---
>  docs/specs/ivshmem_device_spec.txt |  124 +++++++++++++++++++++++++++---------
>  1 file changed, 93 insertions(+), 31 deletions(-)
> 

>  
> -The device currently supports 4 registers of 32-bits each.  Registers
> -are used for synchronization between guests sharing the same memory object when
> -interrupts are supported (this requires using the shared memory server).
> +The server must be started on the host before any guest.
> +It creates a shared memory object then waits for clients to connect on an unix
> +socket.

s/an unix/a unix/

>  
> -The server assigns each VM an ID number and sends this ID number to the QEMU
> -process when the guest starts.
> +For each client (QEMU processes) that connects to the server:

s/processes/process/


> +The client IDs are limited to 16 bits because of the current implementation (see
> +Doorbell register in 'PCI device registers' subsection). Hence on 65536 clients

s/on/only/


> +At initialisation, when creating the ivshmem device, QEMU gets its ID from the
> +server then make it available through BAR0 IVPosition register for the VM to use

s/make/makes/

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 02/14] docs: update ivshmem device spec
@ 2014-09-02 20:24     ` Eric Blake
  0 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:24 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

[-- Attachment #1: Type: text/plain, Size: 1687 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Add some notes on the parts needed to use ivshmem devices: more specifically,
> explain the purpose of an ivshmem server and the basic concept to use the
> ivshmem devices in guests.
> Move some parts of the documentation and re-organise it.
> 
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
> ---
>  docs/specs/ivshmem_device_spec.txt |  124 +++++++++++++++++++++++++++---------
>  1 file changed, 93 insertions(+), 31 deletions(-)
> 

>  
> -The device currently supports 4 registers of 32-bits each.  Registers
> -are used for synchronization between guests sharing the same memory object when
> -interrupts are supported (this requires using the shared memory server).
> +The server must be started on the host before any guest.
> +It creates a shared memory object then waits for clients to connect on an unix
> +socket.

s/an unix/a unix/

>  
> -The server assigns each VM an ID number and sends this ID number to the QEMU
> -process when the guest starts.
> +For each client (QEMU processes) that connects to the server:

s/processes/process/


> +The client IDs are limited to 16 bits because of the current implementation (see
> +Doorbell register in 'PCI device registers' subsection). Hence on 65536 clients

s/on/only/


> +At initialisation, when creating the ivshmem device, QEMU gets its ID from the
> +server then make it available through BAR0 IVPosition register for the VM to use

s/make/makes/

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 05/14] contrib/ivshmem-*: switch to QEMU headers
  2014-09-02 15:25   ` [Qemu-devel] " David Marchand
@ 2014-09-02 20:28     ` Eric Blake
  -1 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:28 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, cam, armbru,
	stefanha, arei.gonglei

[-- Attachment #1: Type: text/plain, Size: 1305 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Reuse parsers from QEMU, C99 boolean.
> 
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> ---
>  contrib/ivshmem-client/ivshmem-client.c |   12 +----
>  contrib/ivshmem-client/ivshmem-client.h |    4 +-
>  contrib/ivshmem-client/main.c           |   12 +----
>  contrib/ivshmem-server/ivshmem-server.c |   14 +-----
>  contrib/ivshmem-server/ivshmem-server.h |    4 +-
>  contrib/ivshmem-server/main.c           |   73 +++++--------------------------
>  6 files changed, 20 insertions(+), 99 deletions(-)

Why introduce code in patch 1 only to rip it back out in patch 5?  Why
not just squash these together and just introduce the contrib file
correct on its first commit?


>  
>          case 'l': /* shm_size */
> -            if (parse_size(optarg, &args->shm_size) < 0) {
> +            parse_option_size("shm_size", optarg, &args->shm_size, &errp);
> +            if (errp) {
> +                error_free(errp);
>                  fprintf(stderr, "cannot parse shm size\n");

It would be nicer to print the contents of errp, instead of discarding
what is likely to be a more specific error message.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 05/14] contrib/ivshmem-*: switch to QEMU headers
@ 2014-09-02 20:28     ` Eric Blake
  0 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:28 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

[-- Attachment #1: Type: text/plain, Size: 1305 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Reuse parsers from QEMU, C99 boolean.
> 
> Signed-off-by: David Marchand <david.marchand@6wind.com>
> ---
>  contrib/ivshmem-client/ivshmem-client.c |   12 +----
>  contrib/ivshmem-client/ivshmem-client.h |    4 +-
>  contrib/ivshmem-client/main.c           |   12 +----
>  contrib/ivshmem-server/ivshmem-server.c |   14 +-----
>  contrib/ivshmem-server/ivshmem-server.h |    4 +-
>  contrib/ivshmem-server/main.c           |   73 +++++--------------------------
>  6 files changed, 20 insertions(+), 99 deletions(-)

Why introduce code in patch 1 only to rip it back out in patch 5?  Why
not just squash these together and just introduce the contrib file
correct on its first commit?


>  
>          case 'l': /* shm_size */
> -            if (parse_size(optarg, &args->shm_size) < 0) {
> +            parse_option_size("shm_size", optarg, &args->shm_size, &errp);
> +            if (errp) {
> +                error_free(errp);
>                  fprintf(stderr, "cannot parse shm size\n");

It would be nicer to print the contents of errp, instead of discarding
what is likely to be a more specific error message.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
  2014-09-02 15:25 ` [Qemu-devel] " David Marchand
@ 2014-09-02 20:31   ` Eric Blake
  -1 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:31 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, pbonzini, claudio.fontana, jani.kokkonen, cam, armbru,
	stefanha, arei.gonglei

[-- Attachment #1: Type: text/plain, Size: 1155 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Here is a patchset containing an update on ivshmem specs documentation and
> importing ivshmem server and client tools.
> These tools have been written from scratch and are not related to what is
> available in nahanni repository.
> I put them in contrib/ directory as the qemu-doc.texi was already telling the
> server was supposed to be there.
> 
> Changes since v3:
> - first patch is untouched
> - just restored the Reviewed-By Claudio in second patch
> - following patches 3-8 take into account Stefan's comments
> - patches 9-12 take into account Gonglei's comments
> - patch 13 adjusts ivshmem-server default values
> - last patch introduces a change in the ivshmem client-server protocol to
>   check a protocol version at connect time

Rather than introducing new files with bugs, followed by patches to
clean it up, why not just introduce the new files correct in the first
place?  I think you are better off squashing in a lot of the cleanup
patches into patch 1.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
@ 2014-09-02 20:31   ` Eric Blake
  0 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-02 20:31 UTC (permalink / raw)
  To: David Marchand, qemu-devel
  Cc: kvm, stefanha, claudio.fontana, armbru, arei.gonglei, pbonzini,
	jani.kokkonen, cam

[-- Attachment #1: Type: text/plain, Size: 1155 bytes --]

On 09/02/2014 09:25 AM, David Marchand wrote:
> Here is a patchset containing an update on ivshmem specs documentation and
> importing ivshmem server and client tools.
> These tools have been written from scratch and are not related to what is
> available in nahanni repository.
> I put them in contrib/ directory as the qemu-doc.texi was already telling the
> server was supposed to be there.
> 
> Changes since v3:
> - first patch is untouched
> - just restored the Reviewed-By Claudio in second patch
> - following patches 3-8 take into account Stefan's comments
> - patches 9-12 take into account Gonglei's comments
> - patch 13 adjusts ivshmem-server default values
> - last patch introduces a change in the ivshmem client-server protocol to
>   check a protocol version at connect time

Rather than introducing new files with bugs, followed by patches to
clean it up, why not just introduce the new files correct in the first
place?  I think you are better off squashing in a lot of the cleanup
patches into patch 1.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
  2014-09-02 20:31   ` [Qemu-devel] " Eric Blake
@ 2014-09-03 13:01     ` David Marchand
  -1 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-03 13:01 UTC (permalink / raw)
  To: Eric Blake
  Cc: kvm, stefanha, claudio.fontana, qemu-devel, armbru, arei.gonglei,
	pbonzini, jani.kokkonen, cam

Hello Eric,

On 09/02/2014 10:31 PM, Eric Blake wrote:
> On 09/02/2014 09:25 AM, David Marchand wrote:
>> Here is a patchset containing an update on ivshmem specs documentation and
>> importing ivshmem server and client tools.
>> These tools have been written from scratch and are not related to what is
>> available in nahanni repository.
>> I put them in contrib/ directory as the qemu-doc.texi was already telling the
>> server was supposed to be there.
>>
>> Changes since v3:
>> - first patch is untouched
>> - just restored the Reviewed-By Claudio in second patch
>> - following patches 3-8 take into account Stefan's comments
>> - patches 9-12 take into account Gonglei's comments
>> - patch 13 adjusts ivshmem-server default values
>> - last patch introduces a change in the ivshmem client-server protocol to
>>    check a protocol version at connect time
>
> Rather than introducing new files with bugs, followed by patches to
> clean it up, why not just introduce the new files correct in the first
> place?  I think you are better off squashing in a lot of the cleanup
> patches into patch 1.

Actually, I mentioned this in a previous email but did not get any comment.
So, I preferred to send the splitted patches to ease review (from my 
point of view).

Once code looks fine enough, I intend to keep only three patches :
- one for the initial import of ivshmem-client / server
- one for the documentation update
- one last with the protocol change

Is it okay this way ?


-- 
David Marchand

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
@ 2014-09-03 13:01     ` David Marchand
  0 siblings, 0 replies; 42+ messages in thread
From: David Marchand @ 2014-09-03 13:01 UTC (permalink / raw)
  To: Eric Blake
  Cc: kvm, stefanha, claudio.fontana, qemu-devel, armbru, arei.gonglei,
	pbonzini, jani.kokkonen, cam

Hello Eric,

On 09/02/2014 10:31 PM, Eric Blake wrote:
> On 09/02/2014 09:25 AM, David Marchand wrote:
>> Here is a patchset containing an update on ivshmem specs documentation and
>> importing ivshmem server and client tools.
>> These tools have been written from scratch and are not related to what is
>> available in nahanni repository.
>> I put them in contrib/ directory as the qemu-doc.texi was already telling the
>> server was supposed to be there.
>>
>> Changes since v3:
>> - first patch is untouched
>> - just restored the Reviewed-By Claudio in second patch
>> - following patches 3-8 take into account Stefan's comments
>> - patches 9-12 take into account Gonglei's comments
>> - patch 13 adjusts ivshmem-server default values
>> - last patch introduces a change in the ivshmem client-server protocol to
>>    check a protocol version at connect time
>
> Rather than introducing new files with bugs, followed by patches to
> clean it up, why not just introduce the new files correct in the first
> place?  I think you are better off squashing in a lot of the cleanup
> patches into patch 1.

Actually, I mentioned this in a previous email but did not get any comment.
So, I preferred to send the splitted patches to ease review (from my 
point of view).

Once code looks fine enough, I intend to keep only three patches :
- one for the initial import of ivshmem-client / server
- one for the documentation update
- one last with the protocol change

Is it okay this way ?


-- 
David Marchand

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
  2014-09-03 13:01     ` [Qemu-devel] " David Marchand
@ 2014-09-03 14:47       ` Eric Blake
  -1 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-03 14:47 UTC (permalink / raw)
  To: David Marchand
  Cc: qemu-devel, kvm, pbonzini, claudio.fontana, jani.kokkonen, cam,
	armbru, stefanha, arei.gonglei

[-- Attachment #1: Type: text/plain, Size: 1265 bytes --]

On 09/03/2014 07:01 AM, David Marchand wrote:

>> Rather than introducing new files with bugs, followed by patches to
>> clean it up, why not just introduce the new files correct in the first
>> place?  I think you are better off squashing in a lot of the cleanup
>> patches into patch 1.
> 
> Actually, I mentioned this in a previous email but did not get any comment.
> So, I preferred to send the splitted patches to ease review (from my
> point of view).

It does not ease reviewer time to have a known buggy patch with later
cleanups.  I'd rather see your best effort at a bug-free patch to begin
with, than to spend my time pointing out bugs only to find out you
already fixed them later in the series.

> 
> Once code looks fine enough, I intend to keep only three patches :
> - one for the initial import of ivshmem-client / server
> - one for the documentation update
> - one last with the protocol change

If that is your plan for the final series, then that is the same plan
you should be using for reviews.  You want the reviewers to see your
proposed final product, not your intermediate state of how you got there.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [Qemu-devel] [PATCH v4 00/14] ivshmem: update documentation, add client/server tools
@ 2014-09-03 14:47       ` Eric Blake
  0 siblings, 0 replies; 42+ messages in thread
From: Eric Blake @ 2014-09-03 14:47 UTC (permalink / raw)
  To: David Marchand
  Cc: kvm, stefanha, claudio.fontana, qemu-devel, armbru, arei.gonglei,
	pbonzini, jani.kokkonen, cam

[-- Attachment #1: Type: text/plain, Size: 1265 bytes --]

On 09/03/2014 07:01 AM, David Marchand wrote:

>> Rather than introducing new files with bugs, followed by patches to
>> clean it up, why not just introduce the new files correct in the first
>> place?  I think you are better off squashing in a lot of the cleanup
>> patches into patch 1.
> 
> Actually, I mentioned this in a previous email but did not get any comment.
> So, I preferred to send the splitted patches to ease review (from my
> point of view).

It does not ease reviewer time to have a known buggy patch with later
cleanups.  I'd rather see your best effort at a bug-free patch to begin
with, than to spend my time pointing out bugs only to find out you
already fixed them later in the series.

> 
> Once code looks fine enough, I intend to keep only three patches :
> - one for the initial import of ivshmem-client / server
> - one for the documentation update
> - one last with the protocol change

If that is your plan for the final series, then that is the same plan
you should be using for reviews.  You want the reviewers to see your
proposed final product, not your intermediate state of how you got there.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2014-09-03 15:50 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-02 15:25 [PATCH v4 00/14] ivshmem: update documentation, add client/server tools David Marchand
2014-09-02 15:25 ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 01/14] contrib: add ivshmem client and server David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 20:20   ` Eric Blake
2014-09-02 20:20     ` [Qemu-devel] " Eric Blake
2014-09-02 15:25 ` [PATCH v4 02/14] docs: update ivshmem device spec David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 20:24   ` Eric Blake
2014-09-02 20:24     ` [Qemu-devel] " Eric Blake
2014-09-02 15:25 ` [PATCH v4 03/14] contrib/ivshmem-*: comply with QEMU coding style David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 04/14] contrib/ivshmem-*: reuse qemu/queue.h David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 05/14] contrib/ivshmem-*: switch to QEMU headers David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 20:28   ` Eric Blake
2014-09-02 20:28     ` [Qemu-devel] " Eric Blake
2014-09-02 15:25 ` [PATCH v4 06/14] contrib/ivshmem-server: set client sockets as non blocking David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 07/14] contrib/ivshmem-*: add missing const and static attrs David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 08/14] contrib/ivshmem-*: plug client and server in QEMU top Makefile David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 09/14] contrib/ivshmem-*: switch to g_malloc0/g_free David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 10/14] contrib/ivshmem-server: fix mem leak on error David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 11/14] contrib/ivshmem-*: rework error handling David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 12/14] contrib/ivshmem-*: various fixes David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 13/14] contrib/ivshmem-server: align server default parameter values David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 15:25 ` [PATCH v4 14/14] ivshmem: add check on protocol version in QEMU David Marchand
2014-09-02 15:25   ` [Qemu-devel] " David Marchand
2014-09-02 20:31 ` [PATCH v4 00/14] ivshmem: update documentation, add client/server tools Eric Blake
2014-09-02 20:31   ` [Qemu-devel] " Eric Blake
2014-09-03 13:01   ` David Marchand
2014-09-03 13:01     ` [Qemu-devel] " David Marchand
2014-09-03 14:47     ` Eric Blake
2014-09-03 14:47       ` [Qemu-devel] " Eric Blake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.