qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5)
@ 2015-08-06 12:40 marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 01/16] configure: probe for memfd marcandre.lureau
                   ` (17 more replies)
  0 siblings, 18 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Hi,

The following series implement shareable log for vhost-user to support
memory tracking during live migration. On qemu-side, the solution is
fairly straightfoward since vhost already supports the dirty log, only
vhost-user couldn't access the log memory until then.

The series is based on top of "protocol feature negotiation" series
proposed earlier by Michael S. Tsirkinm and "vhost user: Add live
migration" series from Thibaut Collet .

Since v2:
- changed some patch summary
- added migration tests
- added a patch to replace error message with a trace

The development branch I used is:
https://github.com/elmarco/qemu branch "vhost-user"

More comments welcome!

Marc-André Lureau (16):
  configure: probe for memfd
  util: add linux-only memfd fallback
  util: add memfd helpers
  vhost: alloc shareable log
  vhost: document log resizing
  vhost: use variable arguments for vhost_call()
  vhost-user: start and end the va_list
  vhost-user: send log shm fd along with log_base
  vhost-user: document migration log
  net: add trace_vhost_user_event
  vhost-user-test: move wait_for_fds() out
  vhost-user-test: remove useless static check
  vhost-user-test: wrap server in TestServer struct
  vhost-user-test: learn to tweak various qemu arguments
  vhost-user-test: add live-migration test
  vhost-user-test: check ownership during migration

 configure                         |  19 ++
 docs/specs/vhost-user.txt         |  42 +++++
 hw/virtio/vhost-backend.c         |   4 +-
 hw/virtio/vhost-user.c            |  52 ++++--
 hw/virtio/vhost.c                 |  45 ++++-
 include/hw/virtio/vhost-backend.h |   6 +-
 include/hw/virtio/vhost.h         |   3 +-
 include/qemu/memfd.h              |  24 +++
 net/vhost-user.c                  |   5 +-
 tests/vhost-user-test.c           | 366 +++++++++++++++++++++++++++++++-------
 trace-events                      |   3 +
 util/Makefile.objs                |   2 +-
 util/memfd.c                      | 126 +++++++++++++
 13 files changed, 602 insertions(+), 95 deletions(-)
 create mode 100644 include/qemu/memfd.h
 create mode 100644 util/memfd.c

-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 01/16] configure: probe for memfd
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 02/16] util: add linux-only memfd fallback marcandre.lureau
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Check if memfd_create() is part of system libc.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 configure | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/configure b/configure
index cd219d8..3dcbd3e 100755
--- a/configure
+++ b/configure
@@ -3405,6 +3405,22 @@ if compile_prog "" "" ; then
   eventfd=yes
 fi
 
+# check if memfd is supported
+memfd=no
+cat > $TMPC << EOF
+#include <sys/memfd.h>
+
+int main(void)
+{
+    return memfd_create("foo", MFD_ALLOW_SEALING);
+}
+EOF
+if compile_prog "" "" ; then
+  memfd=yes
+fi
+
+
+
 # check for fallocate
 fallocate=no
 cat > $TMPC << EOF
@@ -4785,6 +4801,9 @@ fi
 if test "$eventfd" = "yes" ; then
   echo "CONFIG_EVENTFD=y" >> $config_host_mak
 fi
+if test "$memfd" = "yes" ; then
+  echo "CONFIG_MEMFD=y" >> $config_host_mak
+fi
 if test "$fallocate" = "yes" ; then
   echo "CONFIG_FALLOCATE=y" >> $config_host_mak
 fi
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 02/16] util: add linux-only memfd fallback
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 01/16] configure: probe for memfd marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers marcandre.lureau
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Implement memfd_create() fallback if not available in system libc.
memfd_create() is still not included in glibc today, atlhough it's been
available since Linux 3.17 in Oct 2014.

memfd has numerous advantages over traditional shm/mmap for ipc memory
sharing with fd handler, which we are going to make use of for
vhost-user logging memory in following patches.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qemu/memfd.h | 20 +++++++++++++++++++
 util/Makefile.objs   |  2 +-
 util/memfd.c         | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 include/qemu/memfd.h
 create mode 100644 util/memfd.c

diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h
new file mode 100644
index 0000000..8b1fe6a
--- /dev/null
+++ b/include/qemu/memfd.h
@@ -0,0 +1,20 @@
+#ifndef QEMU_MEMFD_H
+#define QEMU_MEMFD_H
+
+#include "config-host.h"
+
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
+#define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
+#define F_SEAL_GROW     0x0004  /* prevent file from growing */
+#define F_SEAL_WRITE    0x0008  /* prevent writes */
+#endif
+
+#endif /* QEMU_MEMFD_H */
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 114d657..84c5485 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -1,6 +1,6 @@
 util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
 util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
-util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
+util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o memfd.o
 util-obj-y += envlist.o path.o module.o
 util-obj-$(call lnot,$(CONFIG_INT128)) += host-utils.o
 util-obj-y += bitmap.o bitops.o hbitmap.o
diff --git a/util/memfd.c b/util/memfd.c
new file mode 100644
index 0000000..a98d57e
--- /dev/null
+++ b/util/memfd.c
@@ -0,0 +1,56 @@
+/*
+ * memfd.c
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * QEMU library functions on POSIX which are shared between QEMU and
+ * the QEMU tools.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "config-host.h"
+
+#include "qemu/memfd.h"
+
+#ifdef CONFIG_MEMFD
+#include <sys/memfd.h>
+#elif defined CONFIG_LINUX
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
+
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+static inline int memfd_create(const char *name, unsigned int flags)
+{
+    return syscall(__NR_memfd_create, name, flags);
+}
+#else /* !LINUX */
+static inline int memfd_create(const char *name, unsigned int flags)
+{
+    return -1;
+}
+#endif
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 01/16] configure: probe for memfd marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 02/16] util: add linux-only memfd fallback marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-09-29 14:57   ` Michael S. Tsirkin
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log marcandre.lureau
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Add qemu_memfd_alloc/free() helpers.

The function helps to allocate and seal a memfd, and implements an
open/unlink/mmap fallback for system that do not support memfd.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qemu/memfd.h |  4 +++
 util/memfd.c         | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h
index 8b1fe6a..950fb88 100644
--- a/include/qemu/memfd.h
+++ b/include/qemu/memfd.h
@@ -17,4 +17,8 @@
 #define F_SEAL_WRITE    0x0008  /* prevent writes */
 #endif
 
+void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
+                       int *fd);
+void qemu_memfd_free(void *ptr, size_t size, int fd);
+
 #endif /* QEMU_MEMFD_H */
diff --git a/util/memfd.c b/util/memfd.c
index a98d57e..8b2b785 100644
--- a/util/memfd.c
+++ b/util/memfd.c
@@ -27,6 +27,14 @@
 
 #include "config-host.h"
 
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
 #include "qemu/memfd.h"
 
 #ifdef CONFIG_MEMFD
@@ -44,13 +52,75 @@
 #define MFD_ALLOW_SEALING 0x0002U
 #endif
 
-static inline int memfd_create(const char *name, unsigned int flags)
+static int memfd_create(const char *name, unsigned int flags)
 {
     return syscall(__NR_memfd_create, name, flags);
 }
 #else /* !LINUX */
-static inline int memfd_create(const char *name, unsigned int flags)
+static int memfd_create(const char *name, unsigned int flags)
 {
     return -1;
 }
 #endif
+
+void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
+                       int *fd)
+{
+    void *ptr;
+    int mfd;
+
+    mfd = memfd_create(name, MFD_ALLOW_SEALING|MFD_CLOEXEC);
+    if (mfd != -1) {
+        if (ftruncate(mfd, size) == -1) {
+            perror("ftruncate");
+            close(mfd);
+            return NULL;
+        }
+
+        if (fcntl(mfd, F_ADD_SEALS, seals) == -1) {
+            perror("fcntl");
+            close(mfd);
+            return NULL;
+        }
+    } else {
+        const char *tmpdir = getenv("TMPDIR");
+        gchar *fname;
+
+        tmpdir = tmpdir ? tmpdir : "/tmp";
+
+        fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir);
+        mfd = mkstemp(fname);
+        unlink(fname);
+        g_free(fname);
+
+        if (mfd == -1) {
+            perror("mkstemp");
+            return NULL;
+        }
+
+        if (ftruncate(mfd, size) == -1) {
+            perror("ftruncate");
+            close(mfd);
+            return NULL;
+        }
+    }
+
+    ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
+    if (ptr == MAP_FAILED) {
+        perror("mmap");
+        close(mfd);
+        return NULL;
+    }
+
+    *fd = mfd;
+    return ptr;
+}
+
+void qemu_memfd_free(void *ptr, size_t size, int fd)
+{
+    if (ptr) {
+        munmap(ptr, size);
+    }
+
+    close(fd);
+}
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (2 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-09-16 14:06   ` Michael S. Tsirkin
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 05/16] vhost: document log resizing marcandre.lureau
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

If the backend is of type VHOST_BACKEND_TYPE_USER, allocate
shareable memory.

Note: vhost_log_get() can use a global "vhost_log" that can be shared by
several vhost devices. We may want instead a common shareable log and a
common non-shareable one.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/virtio/vhost.c         | 38 +++++++++++++++++++++++++++++++-------
 include/hw/virtio/vhost.h |  3 ++-
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 2712c6f..862e786 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -18,6 +18,7 @@
 #include "qemu/atomic.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
+#include "qemu/memfd.h"
 #include <linux/vhost.h>
 #include "exec/address-spaces.h"
 #include "hw/virtio/virtio-bus.h"
@@ -286,20 +287,34 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
     }
     return log_size;
 }
-static struct vhost_log *vhost_log_alloc(uint64_t size)
+
+static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
 {
-    struct vhost_log *log = g_malloc0(sizeof *log + size * sizeof(*(log->log)));
+    struct vhost_log *log;
+    uint64_t logsize = size * sizeof(*(log->log));
+    int fd = -1;
+
+    log = g_new0(struct vhost_log, 1);
+    if (share) {
+        log->log = qemu_memfd_alloc("vhost-log", logsize,
+                                    F_SEAL_GROW|F_SEAL_SHRINK|F_SEAL_SEAL, &fd);
+        memset(log->log, 0, logsize);
+    } else {
+        log->log = g_malloc0(logsize);
+    }
 
     log->size = size;
     log->refcnt = 1;
+    log->fd = fd;
 
     return log;
 }
 
-static struct vhost_log *vhost_log_get(uint64_t size)
+static struct vhost_log *vhost_log_get(uint64_t size, bool share)
 {
-    if (!vhost_log || vhost_log->size != size) {
-        vhost_log = vhost_log_alloc(size);
+    if (!vhost_log || vhost_log->size != size ||
+        (share && vhost_log->fd == -1)) {
+        vhost_log = vhost_log_alloc(size, share);
     } else {
         ++vhost_log->refcnt;
     }
@@ -324,13 +339,21 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync)
         if (vhost_log == log) {
             vhost_log = NULL;
         }
+
+        if (log->fd == -1) {
+            g_free(log->log);
+        } else {
+            qemu_memfd_free(log->log, log->size * sizeof(*(log->log)),
+                            log->fd);
+        }
         g_free(log);
     }
 }
 
 static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
 {
-    struct vhost_log *log = vhost_log_get(size);
+    bool share = dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER;
+    struct vhost_log *log = vhost_log_get(size, share);
     uint64_t log_base = (uintptr_t)log->log;
     int r;
 
@@ -1136,9 +1159,10 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
 
     if (hdev->log_enabled) {
         uint64_t log_base;
+        bool share = hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER;
 
         hdev->log_size = vhost_get_log_size(hdev);
-        hdev->log = vhost_log_get(hdev->log_size);
+        hdev->log = vhost_log_get(hdev->log_size, share);
         log_base = (uintptr_t)hdev->log->log;
         r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
                                         hdev->log_size ? &log_base : NULL);
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 6467c73..ab1dcac 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -31,7 +31,8 @@ typedef unsigned long vhost_log_chunk_t;
 struct vhost_log {
     unsigned long long size;
     int refcnt;
-    vhost_log_chunk_t log[0];
+    int fd;
+    vhost_log_chunk_t *log;
 };
 
 struct vhost_memory;
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 05/16] vhost: document log resizing
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (3 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call() marcandre.lureau
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/virtio/vhost.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 862e786..057d548 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -357,6 +357,8 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
     uint64_t log_base = (uintptr_t)log->log;
     int r;
 
+    /* inform backend of log switching, this must be done before
+       releasing the current log, to ensure no logging is lost */
     r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
     vhost_log_put(dev, true);
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call()
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (4 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 05/16] vhost: document log resizing marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-09-16 14:01   ` Michael S. Tsirkin
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 07/16] vhost-user: start and end the va_list marcandre.lureau
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

It is useful to pass extra arguments to the funtions, for
various backend needs.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/virtio/vhost-backend.c         | 4 ++--
 hw/virtio/vhost-user.c            | 4 ++--
 include/hw/virtio/vhost-backend.h | 6 ++++--
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 4d68a27..7255089 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -14,8 +14,8 @@
 
 #include <sys/ioctl.h>
 
-static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
-                             void *arg)
+static int vhost_kernel_call(struct vhost_dev *dev,
+                             unsigned long int request, void *arg, ...)
 {
     int fd = (uintptr_t) dev->opaque;
 
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 4993b63..8b6d7e7 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -190,8 +190,8 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
             0 : -1;
 }
 
-static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
-        void *arg)
+static int vhost_user_call(struct vhost_dev *dev,
+                           unsigned long int request, void *arg, ...)
 {
     VhostUserMsg msg;
     VhostUserRequest msg_request;
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index e472f29..36fa0f7 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -11,6 +11,8 @@
 #ifndef VHOST_BACKEND_H_
 #define VHOST_BACKEND_H_
 
+#include <stdarg.h>
+
 typedef enum VhostBackendType {
     VHOST_BACKEND_TYPE_NONE = 0,
     VHOST_BACKEND_TYPE_KERNEL = 1,
@@ -20,8 +22,8 @@ typedef enum VhostBackendType {
 
 struct vhost_dev;
 
-typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
-             void *arg);
+typedef int (*vhost_call)(struct vhost_dev *dev,
+                          unsigned long int request, void *arg, ...);
 typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
 typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
 
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 07/16] vhost-user: start and end the va_list
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (5 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call() marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base marcandre.lureau
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Use a common start and exit branch to open and cleanup the va_list.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/virtio/vhost-user.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 8b6d7e7..21ecbcd 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -198,11 +198,13 @@ static int vhost_user_call(struct vhost_dev *dev,
     struct vhost_vring_file *file = 0;
     int need_reply = 0;
     int fds[VHOST_MEMORY_MAX_NREGIONS];
-    int i, fd;
+    int i, fd, ret = 0;
     size_t fd_num = 0;
+    va_list ap;
 
     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
+    va_start(ap, arg);
     msg_request = vhost_user_request_translate(request);
     msg.request = msg_request;
     msg.flags = VHOST_USER_VERSION;
@@ -247,7 +249,8 @@ static int vhost_user_call(struct vhost_dev *dev,
         if (!fd_num) {
             error_report("Failed initializing vhost-user memory map, "
                     "consider using -object memory-backend-file share=on");
-            return -1;
+            ret = -1;
+            goto end;
         }
 
         msg.size = sizeof(m.memory.nregions);
@@ -291,48 +294,53 @@ static int vhost_user_call(struct vhost_dev *dev,
         break;
     default:
         error_report("vhost-user trying to send unhandled ioctl");
-        return -1;
-        break;
+        ret = -1;
+        goto end;
     }
 
     if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
-        return 0;
+        goto end;
     }
 
     if (need_reply) {
         if (vhost_user_read(dev, &msg) < 0) {
-            return 0;
+            goto end;
         }
 
         if (msg_request != msg.request) {
             error_report("Received unexpected msg type."
                     " Expected %d received %d", msg_request, msg.request);
-            return -1;
+            ret = -1;
+            goto end;
         }
 
         switch (msg_request) {
         case VHOST_USER_GET_FEATURES:
             if (msg.size != sizeof(m.u64)) {
                 error_report("Received bad msg size.");
-                return -1;
+                ret = -1;
+                goto end;
             }
             *((__u64 *) arg) = msg.u64;
             break;
         case VHOST_USER_GET_VRING_BASE:
             if (msg.size != sizeof(m.state)) {
                 error_report("Received bad msg size.");
-                return -1;
+                ret = -1;
+                goto end;
             }
             memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
             break;
         default:
             error_report("Received unexpected msg type.");
-            return -1;
-            break;
+            ret = -1;
+            goto end;
         }
     }
 
-    return 0;
+end:
+    va_end(ap);
+    return ret;
 }
 
 static int vhost_user_init(struct vhost_dev *dev, void *opaque)
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (6 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 07/16] vhost-user: start and end the va_list marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-09-16 14:08   ` Michael S. Tsirkin
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 09/16] vhost-user: document migration log marcandre.lureau
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Send the shm for the dirty pages logging if the backend support
VHOST_USER_PROTOCOL_F_LOG_SHMFD.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/virtio/vhost-user.c | 16 ++++++++++++++--
 hw/virtio/vhost.c      |  5 +++--
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 21ecbcd..b2f46a9 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -26,7 +26,9 @@
 #define VHOST_MEMORY_MAX_NREGIONS    8
 
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
-#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
+
+#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x1ULL
+#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
 
 typedef enum VhostUserRequest {
     VHOST_USER_NONE = 0,
@@ -215,8 +217,18 @@ static int vhost_user_call(struct vhost_dev *dev,
         need_reply = 1;
         break;
 
+    case VHOST_USER_SET_LOG_BASE: {
+        struct vhost_log *log = va_arg(ap, struct vhost_log *);
+
+        if (__virtio_has_feature(dev->protocol_features,
+                                 VHOST_USER_PROTOCOL_F_LOG_SHMFD) &&
+            log->fd != -1) {
+            fds[fd_num++] = log->fd;
+        }
+    }
+        /* fall through */
+
     case VHOST_USER_SET_FEATURES:
-    case VHOST_USER_SET_LOG_BASE:
         msg.u64 = *((__u64 *) arg);
         msg.size = sizeof(m.u64);
         break;
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 057d548..ed8b1a5 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -359,7 +359,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
 
     /* inform backend of log switching, this must be done before
        releasing the current log, to ensure no logging is lost */
-    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
+    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base, log);
     assert(r >= 0);
     vhost_log_put(dev, true);
     dev->log = log;
@@ -1167,7 +1167,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
         hdev->log = vhost_log_get(hdev->log_size, share);
         log_base = (uintptr_t)hdev->log->log;
         r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
-                                        hdev->log_size ? &log_base : NULL);
+                                        hdev->log_size ? &log_base : NULL,
+                                        hdev->log);
         if (r < 0) {
             r = -errno;
             goto fail_log;
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 09/16] vhost-user: document migration log
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (7 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 10/16] net: add trace_vhost_user_event marcandre.lureau
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 docs/specs/vhost-user.txt | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
index 0062baa..0322bcf 100644
--- a/docs/specs/vhost-user.txt
+++ b/docs/specs/vhost-user.txt
@@ -120,6 +120,7 @@ There are several messages that the master sends with file descriptors passed
 in the ancillary data:
 
  * VHOST_SET_MEM_TABLE
+ * VHOST_SET_LOG_BASE (if VHOST_USER_PROTOCOL_F_LOG_SHMFD)
  * VHOST_SET_LOG_FD
  * VHOST_SET_VRING_KICK
  * VHOST_SET_VRING_CALL
@@ -135,6 +136,11 @@ As older slaves don't support negotiating protocol features,
 a feature bit was dedicated for this purpose:
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
+Protocol features
+-----------------
+
+#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
+
 Message types
 -------------
 
@@ -301,3 +307,39 @@ Message types
       Bits (0-7) of the payload contain the vring index. Bit 8 is the
       invalid FD flag. This flag is set when there is no file descriptor
       in the ancillary data.
+
+Migration
+---------
+
+During live migration, the master may need to track the modifications
+the slave makes to the memory mapped regions. The client should mark
+the dirty pages in a log. Once it complies to this logging, it may
+declare the VHOST_F_LOG_ALL vhost feature.
+
+All the modifications to memory pointed by vring "descriptor" should
+be marked. Modifications to "used" vring should be marked if
+VHOST_VRING_F_LOG is part of ring's features.
+
+Dirty pages are of size:
+#define VHOST_LOG_PAGE 0x1000
+
+The log memory fd is provided in the ancillary data of
+VHOST_USER_SET_LOG_BASE message when the slave has
+VHOST_USER_PROTOCOL_F_LOG_SHMFD protocol feature.
+
+The size of the log may be computed by using all the known guest
+addresses. The log covers from address 0 to the maximum of guest
+regions. In pseudo-code, to mark page at "addr" as dirty:
+
+page = addr / VHOST_LOG_PAGE
+log[page / 8] |= 1 << page % 8
+
+Use atomic operations, as the log may be concurrently manipulated.
+
+VHOST_USER_SET_LOG_FD is an optional message with an eventfd in
+ancillary data, it may be used to inform the master that the log has
+been modified.
+
+Once the source has finished migration, VHOST_USER_RESET_OWNER message
+will be sent by the source. No further update must be done before the
+destination takes over with new regions & rings.
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 10/16] net: add trace_vhost_user_event
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (8 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 09/16] vhost-user: document migration log marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 11/16] vhost-user-test: move wait_for_fds() out marcandre.lureau
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Replace error_report() and use tracing instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 net/vhost-user.c | 5 +++--
 trace-events     | 3 +++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/vhost-user.c b/net/vhost-user.c
index dc0aa4c..5657992 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -14,6 +14,7 @@
 #include "sysemu/char.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
+#include "trace.h"
 
 typedef struct VhostUserState {
     NetClientState nc;
@@ -123,16 +124,16 @@ static void net_vhost_user_event(void *opaque, int event)
 {
     VhostUserState *s = opaque;
 
+    trace_vhost_user_event(s->chr->label, event);
+
     switch (event) {
     case CHR_EVENT_OPENED:
         vhost_user_start(s);
         net_vhost_link_down(s, false);
-        error_report("chardev \"%s\" went up", s->chr->label);
         break;
     case CHR_EVENT_CLOSED:
         net_vhost_link_down(s, true);
         vhost_user_stop(s);
-        error_report("chardev \"%s\" went down", s->chr->label);
         break;
     }
 }
diff --git a/trace-events b/trace-events
index 94bf3bb..a07b715 100644
--- a/trace-events
+++ b/trace-events
@@ -1654,3 +1654,6 @@ alsa_no_frames(int state) "No frames available and ALSA state is %d"
 # audio/ossaudio.c
 oss_version(int version) "OSS version = %#x"
 oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d"
+
+# net/vhost-user.c
+vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 11/16] vhost-user-test: move wait_for_fds() out
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (9 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 10/16] net: add trace_vhost_user_event marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 12/16] vhost-user-test: remove useless static check marcandre.lureau
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

This function is a precondition for most vhost-user tests.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 228acb6..551a664 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -205,15 +205,11 @@ static GThread *_thread_new(const gchar *name, GThreadFunc func, gpointer data)
     return thread;
 }
 
-static void read_guest_mem(void)
+static void wait_for_fds(void)
 {
-    uint32_t *guest_mem;
     gint64 end_time;
-    int i, j;
-    size_t size;
 
     g_mutex_lock(data_mutex);
-
     end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
     while (!fds_num) {
         if (!_cond_wait_until(data_cond, data_mutex, end_time)) {
@@ -227,6 +223,17 @@ static void read_guest_mem(void)
     g_assert_cmpint(fds_num, >, 0);
     g_assert_cmpint(fds_num, ==, memory.nregions);
 
+    g_mutex_unlock(data_mutex);
+}
+
+static void read_guest_mem(void)
+{
+    uint32_t *guest_mem;
+    int i, j;
+    size_t size;
+
+    wait_for_fds();
+
     /* iterate all regions */
     for (i = 0; i < fds_num; i++) {
 
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 12/16] vhost-user-test: remove useless static check
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (10 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 11/16] vhost-user-test: move wait_for_fds() out marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 13/16] vhost-user-test: wrap server in TestServer struct marcandre.lureau
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 551a664..68badf9 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -262,7 +262,6 @@ static void read_guest_mem(void)
         munmap(guest_mem, memory.regions[i].memory_size);
     }
 
-    g_assert_cmpint(1, ==, 1);
     g_mutex_unlock(data_mutex);
 }
 
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 13/16] vhost-user-test: wrap server in TestServer struct
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (11 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 12/16] vhost-user-test: remove useless static check marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 14/16] vhost-user-test: learn to tweak various qemu arguments marcandre.lureau
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

In the coming patches, a test will use several servers
simultaneously. Wrap the server in a struct, out of the global scope.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 146 ++++++++++++++++++++++++++++++------------------
 1 file changed, 92 insertions(+), 54 deletions(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 68badf9..6605fba 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -115,10 +115,18 @@ static VhostUserMsg m __attribute__ ((unused));
 #define VHOST_USER_VERSION    (0x1)
 /*****************************************************************************/
 
-int fds_num = 0, fds[VHOST_MEMORY_MAX_NREGIONS];
-static VhostUserMemory memory;
-static GMutex *data_mutex;
-static GCond *data_cond;
+typedef struct TestServer {
+    gchar *socket_path;
+    gchar *chr_name;
+    CharDriverState *chr;
+    int fds_num;
+    int fds[VHOST_MEMORY_MAX_NREGIONS];
+    VhostUserMemory memory;
+    GMutex *data_mutex;
+    GCond *data_cond;
+} TestServer;
+
+static const char *hugefs;
 
 static gint64 _get_time(void)
 {
@@ -205,64 +213,63 @@ static GThread *_thread_new(const gchar *name, GThreadFunc func, gpointer data)
     return thread;
 }
 
-static void wait_for_fds(void)
+static void wait_for_fds(TestServer *s)
 {
     gint64 end_time;
 
-    g_mutex_lock(data_mutex);
+    g_mutex_lock(s->data_mutex);
     end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
-    while (!fds_num) {
-        if (!_cond_wait_until(data_cond, data_mutex, end_time)) {
+    while (!s->fds_num) {
+        if (!_cond_wait_until(s->data_cond, s->data_mutex, end_time)) {
             /* timeout has passed */
-            g_assert(fds_num);
+            g_assert(s->fds_num);
             break;
         }
     }
 
     /* check for sanity */
-    g_assert_cmpint(fds_num, >, 0);
-    g_assert_cmpint(fds_num, ==, memory.nregions);
+    g_assert_cmpint(s->fds_num, >, 0);
+    g_assert_cmpint(s->fds_num, ==, s->memory.nregions);
 
-    g_mutex_unlock(data_mutex);
+    g_mutex_unlock(s->data_mutex);
 }
 
-static void read_guest_mem(void)
+static void read_guest_mem(TestServer *s)
 {
     uint32_t *guest_mem;
     int i, j;
     size_t size;
 
-    wait_for_fds();
+    wait_for_fds(s);
 
     /* iterate all regions */
-    for (i = 0; i < fds_num; i++) {
+    for (i = 0; i < s->fds_num; i++) {
 
         /* We'll check only the region statring at 0x0*/
-        if (memory.regions[i].guest_phys_addr != 0x0) {
+        if (s->memory.regions[i].guest_phys_addr != 0x0) {
             continue;
         }
 
-        g_assert_cmpint(memory.regions[i].memory_size, >, 1024);
+        g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
 
-        size =  memory.regions[i].memory_size + memory.regions[i].mmap_offset;
+        size = s->memory.regions[i].memory_size +
+            s->memory.regions[i].mmap_offset;
 
         guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
-                         MAP_SHARED, fds[i], 0);
+                         MAP_SHARED, s->fds[i], 0);
 
         g_assert(guest_mem != MAP_FAILED);
-        guest_mem += (memory.regions[i].mmap_offset / sizeof(*guest_mem));
+        guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
 
         for (j = 0; j < 256; j++) {
-            uint32_t a = readl(memory.regions[i].guest_phys_addr + j*4);
+            uint32_t a = readl(s->memory.regions[i].guest_phys_addr + j*4);
             uint32_t b = guest_mem[j];
 
             g_assert_cmpint(a, ==, b);
         }
 
-        munmap(guest_mem, memory.regions[i].memory_size);
+        munmap(guest_mem, s->memory.regions[i].memory_size);
     }
-
-    g_mutex_unlock(data_mutex);
 }
 
 static void *thread_function(void *data)
@@ -280,7 +287,8 @@ static int chr_can_read(void *opaque)
 
 static void chr_read(void *opaque, const uint8_t *buf, int size)
 {
-    CharDriverState *chr = opaque;
+    TestServer *s = opaque;
+    CharDriverState *chr = s->chr;
     VhostUserMsg msg;
     uint8_t *p = (uint8_t *) &msg;
     int fd;
@@ -290,12 +298,12 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         return;
     }
 
-    g_mutex_lock(data_mutex);
+    g_mutex_lock(s->data_mutex);
     memcpy(p, buf, VHOST_USER_HDR_SIZE);
 
     if (msg.size) {
         p += VHOST_USER_HDR_SIZE;
-        qemu_chr_fe_read_all(chr, p, msg.size);
+        g_assert_cmpint(qemu_chr_fe_read_all(chr, p, msg.size), ==, msg.size);
     }
 
     switch (msg.request) {
@@ -334,11 +342,11 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 
     case VHOST_USER_SET_MEM_TABLE:
         /* received the mem table */
-        memcpy(&memory, &msg.memory, sizeof(msg.memory));
-        fds_num = qemu_chr_fe_get_msgfds(chr, fds, sizeof(fds) / sizeof(int));
+        memcpy(&s->memory, &msg.memory, sizeof(msg.memory));
+        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds, G_N_ELEMENTS(s->fds));
 
         /* signal the test that it can continue */
-        g_cond_signal(data_cond);
+        g_cond_signal(s->data_cond);
         break;
 
     case VHOST_USER_SET_VRING_KICK:
@@ -355,7 +363,53 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
     default:
         break;
     }
-    g_mutex_unlock(data_mutex);
+
+    g_mutex_unlock(s->data_mutex);
+}
+
+static TestServer *test_server_new(const gchar *name)
+{
+    TestServer *server = g_new0(TestServer, 1);
+    gchar *chr_path;
+
+    server->socket_path = g_strdup_printf("/tmp/vhost-%s-%d.sock",
+                                          name, getpid());
+
+    chr_path = g_strdup_printf("unix:%s,server,nowait", server->socket_path);
+    server->chr_name = g_strdup_printf("chr-%s", name);
+    server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+    g_free(chr_path);
+
+    qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
+
+    /* run the main loop thread so the chardev may operate */
+    server->data_mutex = _mutex_new();
+    server->data_cond = _cond_new();
+
+    return server;
+}
+
+#define GET_QEMU_CMD(s)                                         \
+    g_strdup_printf(QEMU_CMD, (hugefs), (s)->socket_path)
+
+
+static void test_server_free(TestServer *server)
+{
+    int i;
+
+    qemu_chr_delete(server->chr);
+
+    for (i = 0; i < server->fds_num; i++) {
+        close(server->fds[i]);
+    }
+
+    unlink(server->socket_path);
+    g_free(server->socket_path);
+
+    _cond_free(server->data_cond);
+    _mutex_free(server->data_mutex);
+
+    g_free(server);
 }
 
 static const char *init_hugepagefs(void)
@@ -394,41 +448,28 @@ static const char *init_hugepagefs(void)
 int main(int argc, char **argv)
 {
     QTestState *s = NULL;
-    CharDriverState *chr = NULL;
-    const char *hugefs = 0;
-    char *socket_path = 0;
-    char *qemu_cmd = 0;
-    char *chr_path = 0;
+    TestServer *server = NULL;
+    char *qemu_cmd;
     int ret;
 
     g_test_init(&argc, &argv, NULL);
 
     module_call_init(MODULE_INIT_QOM);
+    qemu_add_opts(&qemu_chardev_opts);
 
     hugefs = init_hugepagefs();
     if (!hugefs) {
         return 0;
     }
 
-    socket_path = g_strdup_printf("/tmp/vhost-%d.sock", getpid());
-
-    /* create char dev and add read handlers */
-    qemu_add_opts(&qemu_chardev_opts);
-    chr_path = g_strdup_printf("unix:%s,server,nowait", socket_path);
-    chr = qemu_chr_new("chr0", chr_path, NULL);
-    g_free(chr_path);
-    qemu_chr_add_handlers(chr, chr_can_read, chr_read, NULL, chr);
-
-    /* run the main loop thread so the chardev may operate */
-    data_mutex = _mutex_new();
-    data_cond = _cond_new();
     _thread_new(NULL, thread_function, NULL);
 
-    qemu_cmd = g_strdup_printf(QEMU_CMD, hugefs, socket_path);
+    server = test_server_new("test");
+    qemu_cmd = GET_QEMU_CMD(server);
     s = qtest_start(qemu_cmd);
     g_free(qemu_cmd);
 
-    qtest_add_func("/vhost-user/read-guest-mem", read_guest_mem);
+    qtest_add_data_func("/vhost-user/read-guest-mem", server, read_guest_mem);
 
     ret = g_test_run();
 
@@ -437,10 +478,7 @@ int main(int argc, char **argv)
     }
 
     /* cleanup */
-    unlink(socket_path);
-    g_free(socket_path);
-    _cond_free(data_cond);
-    _mutex_free(data_mutex);
+    test_server_free(server);
 
     return ret;
 }
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 14/16] vhost-user-test: learn to tweak various qemu arguments
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (12 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 13/16] vhost-user-test: wrap server in TestServer struct marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 15/16] vhost-user-test: add live-migration test marcandre.lureau
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Add a new macro to make the qemu command line with other
values of memory size, and specific chardev id.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 6605fba..4ef2d6c 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -37,10 +37,10 @@
 #endif
 
 #define QEMU_CMD_ACCEL  " -machine accel=tcg"
-#define QEMU_CMD_MEM    " -m 512 -object memory-backend-file,id=mem,size=512M,"\
+#define QEMU_CMD_MEM    " -m %d -object memory-backend-file,id=mem,size=%dM,"\
                         "mem-path=%s,share=on -numa node,memdev=mem"
-#define QEMU_CMD_CHR    " -chardev socket,id=chr0,path=%s"
-#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=chr0,vhostforce"
+#define QEMU_CMD_CHR    " -chardev socket,id=%s,path=%s"
+#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
 #define QEMU_CMD_NET    " -device virtio-net-pci,netdev=net0 "
 #define QEMU_CMD_ROM    " -option-rom ../pc-bios/pxe-virtio.rom"
 
@@ -389,9 +389,13 @@ static TestServer *test_server_new(const gchar *name)
     return server;
 }
 
-#define GET_QEMU_CMD(s)                                         \
-    g_strdup_printf(QEMU_CMD, (hugefs), (s)->socket_path)
+#define GET_QEMU_CMD(s)                                 \
+    g_strdup_printf(QEMU_CMD, 512, 512, (hugefs),       \
+        (s)->chr_name, (s)->socket_path, (s)->chr_name)
 
+#define GET_QEMU_CMDE(s, mem, extra, ...)                               \
+    g_strdup_printf(QEMU_CMD extra, (mem), (mem), (hugefs),             \
+        (s)->chr_name, (s)->socket_path, (s)->chr_name, ##__VA_ARGS__)
 
 static void test_server_free(TestServer *server)
 {
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 15/16] vhost-user-test: add live-migration test
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (13 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 14/16] vhost-user-test: learn to tweak various qemu arguments marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 16/16] vhost-user-test: check ownership during migration marcandre.lureau
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

This test checks that the log fd is given to the migration source, and
mark dirty pages during migration.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 159 insertions(+), 3 deletions(-)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 4ef2d6c..dcc14bf 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -13,6 +13,7 @@
 
 #include "libqtest.h"
 #include "qemu/option.h"
+#include "qemu/range.h"
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
 
@@ -54,6 +55,9 @@
 #define VHOST_MEMORY_MAX_NREGIONS    8
 
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
+#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
+
+#define VHOST_LOG_PAGE 0x1000
 
 typedef enum VhostUserRequest {
     VHOST_USER_NONE = 0,
@@ -124,6 +128,7 @@ typedef struct TestServer {
     VhostUserMemory memory;
     GMutex *data_mutex;
     GCond *data_cond;
+    int log_fd;
 } TestServer;
 
 static const char *hugefs;
@@ -311,7 +316,8 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         /* send back features to qemu */
         msg.flags |= VHOST_USER_REPLY_MASK;
         msg.size = sizeof(m.u64);
-        msg.u64 = 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
+        msg.u64 = 0x1ULL << VHOST_F_LOG_ALL |
+            0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
         p = (uint8_t *) &msg;
         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
         break;
@@ -325,12 +331,11 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         /* send back features to qemu */
         msg.flags |= VHOST_USER_REPLY_MASK;
         msg.size = sizeof(m.u64);
-        msg.u64 = 0;
+        msg.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
         p = (uint8_t *) &msg;
         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
         break;
 
-
     case VHOST_USER_GET_VRING_BASE:
         /* send back vring base to qemu */
         msg.flags |= VHOST_USER_REPLY_MASK;
@@ -360,6 +365,12 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
          */
         qemu_set_nonblock(fd);
         break;
+
+    case VHOST_USER_SET_LOG_BASE:
+        qemu_chr_fe_get_msgfds(chr, &s->log_fd, 1);
+        g_cond_signal(s->data_cond);
+        break;
+
     default:
         break;
     }
@@ -386,6 +397,8 @@ static TestServer *test_server_new(const gchar *name)
     server->data_mutex = _mutex_new();
     server->data_cond = _cond_new();
 
+    server->log_fd = -1;
+
     return server;
 }
 
@@ -407,15 +420,157 @@ static void test_server_free(TestServer *server)
         close(server->fds[i]);
     }
 
+    if (server->log_fd != -1) {
+        close(server->log_fd);
+    }
+
     unlink(server->socket_path);
     g_free(server->socket_path);
 
     _cond_free(server->data_cond);
     _mutex_free(server->data_mutex);
 
+    g_free(server->chr_name);
     g_free(server);
 }
 
+static void wait_for_log_fd(TestServer *s)
+{
+    gint64 end_time;
+
+    g_mutex_lock(s->data_mutex);
+    end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
+    while (s->log_fd == -1) {
+        if (!_cond_wait_until(s->data_cond, s->data_mutex, end_time)) {
+            /* timeout has passed */
+            g_assert(s->log_fd != -1);
+            break;
+        }
+    }
+
+    g_mutex_unlock(s->data_mutex);
+}
+
+static void write_guest_mem(TestServer *s, uint32 seed)
+{
+    uint32_t *guest_mem;
+    int i, j;
+    size_t size;
+
+    wait_for_fds(s);
+
+    /* iterate all regions */
+    for (i = 0; i < s->fds_num; i++) {
+
+        /* We'll write only the region statring at 0x0 */
+        if (s->memory.regions[i].guest_phys_addr != 0x0) {
+            continue;
+        }
+
+        g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
+
+        size = s->memory.regions[i].memory_size +
+            s->memory.regions[i].mmap_offset;
+
+        guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
+                         MAP_SHARED, s->fds[i], 0);
+
+        g_assert(guest_mem != MAP_FAILED);
+        guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
+
+        for (j = 0; j < 256; j++) {
+            guest_mem[j] = seed + j;
+        }
+
+        munmap(guest_mem, s->memory.regions[i].memory_size);
+        break;
+    }
+}
+
+static guint64 get_log_size(TestServer *s)
+{
+    guint64 log_size = 0;
+    int i;
+
+    for (i = 0; i < s->memory.nregions; ++i) {
+        VhostUserMemoryRegion *reg = &s->memory.regions[i];
+        guint64 last = range_get_last(reg->guest_phys_addr,
+                                       reg->memory_size);
+        log_size = MAX(log_size, last / (8 * VHOST_LOG_PAGE) + 1);
+    }
+
+    return log_size;
+}
+
+static void test_migrate(void)
+{
+    TestServer *s = test_server_new("src");
+    TestServer *dest = test_server_new("dest");
+    const char *uri = "tcp:127.0.0.1:1234";
+    QTestState *global = global_qtest, *from, *to;
+    gchar *cmd;
+    QDict *rsp;
+    guint8 *log;
+    guint64 size;
+
+    cmd = GET_QEMU_CMDE(s, 2, "");
+    from = qtest_start(cmd);
+    g_free(cmd);
+
+    wait_for_fds(s);
+    size = get_log_size(s);
+    g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
+
+    cmd = GET_QEMU_CMDE(dest, 2, " -incoming %s", uri);
+    to = qtest_init(cmd);
+    g_free(cmd);
+
+    /* slow down migration to have time to fiddle with log */
+    /* TODO: qtest could learn to break on some places */
+    rsp = qmp("{ 'execute': 'migrate_set_speed',"
+              "'arguments': { 'value': 10 } }");
+    g_assert(qdict_haskey(rsp, "return"));
+    QDECREF(rsp);
+
+    cmd = g_strdup_printf("{ 'execute': 'migrate',"
+                          "'arguments': { 'uri': '%s' } }",
+                          uri);
+    rsp = qmp(cmd);
+    g_free(cmd);
+    g_assert(qdict_haskey(rsp, "return"));
+    QDECREF(rsp);
+
+    wait_for_log_fd(s);
+
+    log = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, s->log_fd, 0);
+    g_assert(log != MAP_FAILED);
+
+    /* modify first page */
+    write_guest_mem(s, 0x42);
+    log[0] = 1;
+    munmap(log, size);
+
+    /* speed things up */
+    rsp = qmp("{ 'execute': 'migrate_set_speed',"
+              "'arguments': { 'value': 0 } }");
+    g_assert(qdict_haskey(rsp, "return"));
+    QDECREF(rsp);
+
+    qmp_eventwait("STOP");
+
+    global_qtest = to;
+    qmp_eventwait("RESUME");
+
+    read_guest_mem(dest);
+
+    qtest_quit(to);
+    test_server_free(dest);
+    qtest_quit(from);
+    test_server_free(s);
+
+    global_qtest = global;
+}
+
 static const char *init_hugepagefs(void)
 {
     const char *path;
@@ -474,6 +629,7 @@ int main(int argc, char **argv)
     g_free(qemu_cmd);
 
     qtest_add_data_func("/vhost-user/read-guest-mem", server, read_guest_mem);
+    qtest_add_func("/vhost-user/migrate", test_migrate);
 
     ret = g_test_run();
 
-- 
2.4.3

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

* [Qemu-devel] [PATCH v3 16/16] vhost-user-test: check ownership during migration
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (14 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 15/16] vhost-user-test: add live-migration test marcandre.lureau
@ 2015-08-06 12:40 ` marcandre.lureau
  2015-09-16 14:02 ` [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) Michael S. Tsirkin
  2015-09-16 14:46 ` Michael S. Tsirkin
  17 siblings, 0 replies; 28+ messages in thread
From: marcandre.lureau @ 2015-08-06 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: haifeng.lin, mst, thibaut.collet, jasowang, pbonzini,
	Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Check that backend source and destination do not have simultaneous
ownership during migration.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 tests/vhost-user-test.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index dcc14bf..f78483d 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -371,6 +371,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         g_cond_signal(s->data_cond);
         break;
 
+    case VHOST_USER_RESET_OWNER:
+        s->fds_num = 0;
+        break;
+
     default:
         break;
     }
@@ -502,12 +506,37 @@ static guint64 get_log_size(TestServer *s)
     return log_size;
 }
 
+typedef struct TestMigrateSource {
+    GSource source;
+    TestServer *src;
+    TestServer *dest;
+} TestMigrateSource;
+
+static gboolean
+test_migrate_source_check(GSource *source)
+{
+    TestMigrateSource *t = (TestMigrateSource *)source;
+    gboolean overlap = t->src->fds_num > 0 && t->dest->fds_num > 0;
+
+    g_assert(!overlap);
+
+    return FALSE;
+}
+
+GSourceFuncs test_migrate_source_funcs = {
+    NULL,
+    test_migrate_source_check,
+    NULL,
+    NULL
+};
+
 static void test_migrate(void)
 {
     TestServer *s = test_server_new("src");
     TestServer *dest = test_server_new("dest");
     const char *uri = "tcp:127.0.0.1:1234";
     QTestState *global = global_qtest, *from, *to;
+    GSource *source;
     gchar *cmd;
     QDict *rsp;
     guint8 *log;
@@ -525,6 +554,12 @@ static void test_migrate(void)
     to = qtest_init(cmd);
     g_free(cmd);
 
+    source = g_source_new(&test_migrate_source_funcs,
+                          sizeof(TestMigrateSource));
+    ((TestMigrateSource *)source)->src = s;
+    ((TestMigrateSource *)source)->dest = dest;
+    g_source_attach(source, NULL);
+
     /* slow down migration to have time to fiddle with log */
     /* TODO: qtest could learn to break on some places */
     rsp = qmp("{ 'execute': 'migrate_set_speed',"
@@ -563,6 +598,9 @@ static void test_migrate(void)
 
     read_guest_mem(dest);
 
+    g_source_destroy(source);
+    g_source_unref(source);
+
     qtest_quit(to);
     test_server_free(dest);
     qtest_quit(from);
-- 
2.4.3

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

* Re: [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call()
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call() marcandre.lureau
@ 2015-09-16 14:01   ` Michael S. Tsirkin
  2015-09-19  8:58     ` Marc-André Lureau
  0 siblings, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-16 14:01 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: haifeng.lin, thibaut.collet, jasowang, qemu-devel, pbonzini

On Thu, Aug 06, 2015 at 02:40:42PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> It is useful to pass extra arguments to the funtions, for
> various backend needs.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Let's not do this.
It's probably time to replace vhost_call with an ops struct of functions.
This will solve this in a clean way.


> ---
>  hw/virtio/vhost-backend.c         | 4 ++--
>  hw/virtio/vhost-user.c            | 4 ++--
>  include/hw/virtio/vhost-backend.h | 6 ++++--
>  3 files changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
> index 4d68a27..7255089 100644
> --- a/hw/virtio/vhost-backend.c
> +++ b/hw/virtio/vhost-backend.c
> @@ -14,8 +14,8 @@
>  
>  #include <sys/ioctl.h>
>  
> -static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
> -                             void *arg)
> +static int vhost_kernel_call(struct vhost_dev *dev,
> +                             unsigned long int request, void *arg, ...)
>  {
>      int fd = (uintptr_t) dev->opaque;
>  
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 4993b63..8b6d7e7 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -190,8 +190,8 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
>              0 : -1;
>  }
>  
> -static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> -        void *arg)
> +static int vhost_user_call(struct vhost_dev *dev,
> +                           unsigned long int request, void *arg, ...)
>  {
>      VhostUserMsg msg;
>      VhostUserRequest msg_request;
> diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
> index e472f29..36fa0f7 100644
> --- a/include/hw/virtio/vhost-backend.h
> +++ b/include/hw/virtio/vhost-backend.h
> @@ -11,6 +11,8 @@
>  #ifndef VHOST_BACKEND_H_
>  #define VHOST_BACKEND_H_
>  
> +#include <stdarg.h>
> +
>  typedef enum VhostBackendType {
>      VHOST_BACKEND_TYPE_NONE = 0,
>      VHOST_BACKEND_TYPE_KERNEL = 1,
> @@ -20,8 +22,8 @@ typedef enum VhostBackendType {
>  
>  struct vhost_dev;
>  
> -typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
> -             void *arg);
> +typedef int (*vhost_call)(struct vhost_dev *dev,
> +                          unsigned long int request, void *arg, ...);
>  typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
>  typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
>  
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5)
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (15 preceding siblings ...)
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 16/16] vhost-user-test: check ownership during migration marcandre.lureau
@ 2015-09-16 14:02 ` Michael S. Tsirkin
  2015-09-16 14:46 ` Michael S. Tsirkin
  17 siblings, 0 replies; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-16 14:02 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: haifeng.lin, thibaut.collet, jasowang, qemu-devel, pbonzini

On Thu, Aug 06, 2015 at 02:40:36PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Hi,
> 
> The following series implement shareable log for vhost-user to support
> memory tracking during live migration. On qemu-side, the solution is
> fairly straightfoward since vhost already supports the dirty log, only
> vhost-user couldn't access the log memory until then.
> 
> The series is based on top of "protocol feature negotiation" series
> proposed earlier by Michael S. Tsirkinm and "vhost user: Add live
> migration" series from Thibaut Collet .

I'd prefer to see the whole series included in the post.

This looks pretty clean, I have some minor comments.


> Since v2:
> - changed some patch summary
> - added migration tests
> - added a patch to replace error message with a trace
> 
> The development branch I used is:
> https://github.com/elmarco/qemu branch "vhost-user"
> 
> More comments welcome!
> 
> Marc-André Lureau (16):
>   configure: probe for memfd
>   util: add linux-only memfd fallback
>   util: add memfd helpers
>   vhost: alloc shareable log
>   vhost: document log resizing
>   vhost: use variable arguments for vhost_call()
>   vhost-user: start and end the va_list
>   vhost-user: send log shm fd along with log_base
>   vhost-user: document migration log
>   net: add trace_vhost_user_event
>   vhost-user-test: move wait_for_fds() out
>   vhost-user-test: remove useless static check
>   vhost-user-test: wrap server in TestServer struct
>   vhost-user-test: learn to tweak various qemu arguments
>   vhost-user-test: add live-migration test
>   vhost-user-test: check ownership during migration
> 
>  configure                         |  19 ++
>  docs/specs/vhost-user.txt         |  42 +++++
>  hw/virtio/vhost-backend.c         |   4 +-
>  hw/virtio/vhost-user.c            |  52 ++++--
>  hw/virtio/vhost.c                 |  45 ++++-
>  include/hw/virtio/vhost-backend.h |   6 +-
>  include/hw/virtio/vhost.h         |   3 +-
>  include/qemu/memfd.h              |  24 +++
>  net/vhost-user.c                  |   5 +-
>  tests/vhost-user-test.c           | 366 +++++++++++++++++++++++++++++++-------
>  trace-events                      |   3 +
>  util/Makefile.objs                |   2 +-
>  util/memfd.c                      | 126 +++++++++++++
>  13 files changed, 602 insertions(+), 95 deletions(-)
>  create mode 100644 include/qemu/memfd.h
>  create mode 100644 util/memfd.c
> 
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log marcandre.lureau
@ 2015-09-16 14:06   ` Michael S. Tsirkin
  2015-09-19  9:01     ` Marc-André Lureau
  0 siblings, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-16 14:06 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: haifeng.lin, thibaut.collet, jasowang, qemu-devel, pbonzini

On Thu, Aug 06, 2015 at 02:40:40PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> If the backend is of type VHOST_BACKEND_TYPE_USER, allocate
> shareable memory.
> 
> Note: vhost_log_get() can use a global "vhost_log" that can be shared by
> several vhost devices. We may want instead a common shareable log and a
> common non-shareable one.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Shouldn't this be limited to when the appropriate feature flag
is negotiated?


> ---
>  hw/virtio/vhost.c         | 38 +++++++++++++++++++++++++++++++-------
>  include/hw/virtio/vhost.h |  3 ++-
>  2 files changed, 33 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index 2712c6f..862e786 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -18,6 +18,7 @@
>  #include "qemu/atomic.h"
>  #include "qemu/range.h"
>  #include "qemu/error-report.h"
> +#include "qemu/memfd.h"
>  #include <linux/vhost.h>
>  #include "exec/address-spaces.h"
>  #include "hw/virtio/virtio-bus.h"
> @@ -286,20 +287,34 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
>      }
>      return log_size;
>  }
> -static struct vhost_log *vhost_log_alloc(uint64_t size)
> +
> +static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
>  {
> -    struct vhost_log *log = g_malloc0(sizeof *log + size * sizeof(*(log->log)));
> +    struct vhost_log *log;
> +    uint64_t logsize = size * sizeof(*(log->log));
> +    int fd = -1;
> +
> +    log = g_new0(struct vhost_log, 1);
> +    if (share) {
> +        log->log = qemu_memfd_alloc("vhost-log", logsize,
> +                                    F_SEAL_GROW|F_SEAL_SHRINK|F_SEAL_SEAL, &fd);
> +        memset(log->log, 0, logsize);
> +    } else {
> +        log->log = g_malloc0(logsize);
> +    }
>  
>      log->size = size;
>      log->refcnt = 1;
> +    log->fd = fd;
>  
>      return log;
>  }
>  
> -static struct vhost_log *vhost_log_get(uint64_t size)
> +static struct vhost_log *vhost_log_get(uint64_t size, bool share)
>  {
> -    if (!vhost_log || vhost_log->size != size) {
> -        vhost_log = vhost_log_alloc(size);
> +    if (!vhost_log || vhost_log->size != size ||
> +        (share && vhost_log->fd == -1)) {
> +        vhost_log = vhost_log_alloc(size, share);
>      } else {
>          ++vhost_log->refcnt;
>      }
> @@ -324,13 +339,21 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync)
>          if (vhost_log == log) {
>              vhost_log = NULL;
>          }
> +
> +        if (log->fd == -1) {
> +            g_free(log->log);
> +        } else {
> +            qemu_memfd_free(log->log, log->size * sizeof(*(log->log)),
> +                            log->fd);
> +        }
>          g_free(log);
>      }
>  }
>  
>  static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
>  {
> -    struct vhost_log *log = vhost_log_get(size);
> +    bool share = dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER;
> +    struct vhost_log *log = vhost_log_get(size, share);
>      uint64_t log_base = (uintptr_t)log->log;
>      int r;
>  
> @@ -1136,9 +1159,10 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
>  
>      if (hdev->log_enabled) {
>          uint64_t log_base;
> +        bool share = hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER;
>  
>          hdev->log_size = vhost_get_log_size(hdev);
> -        hdev->log = vhost_log_get(hdev->log_size);
> +        hdev->log = vhost_log_get(hdev->log_size, share);
>          log_base = (uintptr_t)hdev->log->log;
>          r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
>                                          hdev->log_size ? &log_base : NULL);
> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
> index 6467c73..ab1dcac 100644
> --- a/include/hw/virtio/vhost.h
> +++ b/include/hw/virtio/vhost.h
> @@ -31,7 +31,8 @@ typedef unsigned long vhost_log_chunk_t;
>  struct vhost_log {
>      unsigned long long size;
>      int refcnt;
> -    vhost_log_chunk_t log[0];
> +    int fd;
> +    vhost_log_chunk_t *log;
>  };
>  
>  struct vhost_memory;
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base marcandre.lureau
@ 2015-09-16 14:08   ` Michael S. Tsirkin
  2015-09-19  8:59     ` Marc-André Lureau
  0 siblings, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-16 14:08 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: haifeng.lin, thibaut.collet, jasowang, qemu-devel, pbonzini

On Thu, Aug 06, 2015 at 02:40:44PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Send the shm for the dirty pages logging if the backend support

supports

> VHOST_USER_PROTOCOL_F_LOG_SHMFD.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/virtio/vhost-user.c | 16 ++++++++++++++--
>  hw/virtio/vhost.c      |  5 +++--
>  2 files changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 21ecbcd..b2f46a9 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -26,7 +26,9 @@
>  #define VHOST_MEMORY_MAX_NREGIONS    8
>  
>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> +
> +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x1ULL
> +#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
>  
>  typedef enum VhostUserRequest {
>      VHOST_USER_NONE = 0,
> @@ -215,8 +217,18 @@ static int vhost_user_call(struct vhost_dev *dev,
>          need_reply = 1;
>          break;
>  
> +    case VHOST_USER_SET_LOG_BASE: {
> +        struct vhost_log *log = va_arg(ap, struct vhost_log *);
> +
> +        if (__virtio_has_feature(dev->protocol_features,
> +                                 VHOST_USER_PROTOCOL_F_LOG_SHMFD) &&
> +            log->fd != -1) {
> +            fds[fd_num++] = log->fd;
> +        }
> +    }
> +        /* fall through */
> +

Don't add {} like that please. Just move declarations to the top level.


>      case VHOST_USER_SET_FEATURES:
> -    case VHOST_USER_SET_LOG_BASE:
>          msg.u64 = *((__u64 *) arg);
>          msg.size = sizeof(m.u64);
>          break;
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index 057d548..ed8b1a5 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -359,7 +359,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
>  
>      /* inform backend of log switching, this must be done before
>         releasing the current log, to ensure no logging is lost */
> -    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
> +    r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base, log);
>      assert(r >= 0);
>      vhost_log_put(dev, true);
>      dev->log = log;
> @@ -1167,7 +1167,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
>          hdev->log = vhost_log_get(hdev->log_size, share);
>          log_base = (uintptr_t)hdev->log->log;
>          r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
> -                                        hdev->log_size ? &log_base : NULL);
> +                                        hdev->log_size ? &log_base : NULL,
> +                                        hdev->log);
>          if (r < 0) {
>              r = -errno;
>              goto fail_log;
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5)
  2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
                   ` (16 preceding siblings ...)
  2015-09-16 14:02 ` [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) Michael S. Tsirkin
@ 2015-09-16 14:46 ` Michael S. Tsirkin
  17 siblings, 0 replies; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-16 14:46 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: aarcange, haifeng.lin, thibaut.collet, jasowang, qemu-devel,
	pbonzini

On Thu, Aug 06, 2015 at 02:40:36PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Hi,
> 
> The following series implement shareable log for vhost-user to support
> memory tracking during live migration. On qemu-side, the solution is
> fairly straightfoward since vhost already supports the dirty log, only
> vhost-user couldn't access the log memory until then.
> 
> The series is based on top of "protocol feature negotiation" series
> proposed earlier by Michael S. Tsirkinm and "vhost user: Add live
> migration" series from Thibaut Collet .

I've been thinking about this. I wonder whether an alternative
approach would make sense.
Specifically, write protect the pages we want to track in host
PTEs; on a page fault, log the change (in kernel) and restart.

This could work for all of vhost, userspace qemu, vhost-user
transparently (so we don't need to teach dpdk to do
dirty logging).
It would be more robust since it removes the ability for
a buggy userspace to change memory without logging it.

And it would be faster since log is only set on the 1st
write, afterwards page is writeable - so no fault.

It's a kernel patch so more work.

I guess we can support both approaches (e.g. for old kernels)
but I thought I'd through this out there.


> Since v2:
> - changed some patch summary
> - added migration tests
> - added a patch to replace error message with a trace
> 
> The development branch I used is:
> https://github.com/elmarco/qemu branch "vhost-user"
> 
> More comments welcome!
> 
> Marc-André Lureau (16):
>   configure: probe for memfd
>   util: add linux-only memfd fallback
>   util: add memfd helpers
>   vhost: alloc shareable log
>   vhost: document log resizing
>   vhost: use variable arguments for vhost_call()
>   vhost-user: start and end the va_list
>   vhost-user: send log shm fd along with log_base
>   vhost-user: document migration log
>   net: add trace_vhost_user_event
>   vhost-user-test: move wait_for_fds() out
>   vhost-user-test: remove useless static check
>   vhost-user-test: wrap server in TestServer struct
>   vhost-user-test: learn to tweak various qemu arguments
>   vhost-user-test: add live-migration test
>   vhost-user-test: check ownership during migration
> 
>  configure                         |  19 ++
>  docs/specs/vhost-user.txt         |  42 +++++
>  hw/virtio/vhost-backend.c         |   4 +-
>  hw/virtio/vhost-user.c            |  52 ++++--
>  hw/virtio/vhost.c                 |  45 ++++-
>  include/hw/virtio/vhost-backend.h |   6 +-
>  include/hw/virtio/vhost.h         |   3 +-
>  include/qemu/memfd.h              |  24 +++
>  net/vhost-user.c                  |   5 +-
>  tests/vhost-user-test.c           | 366 +++++++++++++++++++++++++++++++-------
>  trace-events                      |   3 +
>  util/Makefile.objs                |   2 +-
>  util/memfd.c                      | 126 +++++++++++++
>  13 files changed, 602 insertions(+), 95 deletions(-)
>  create mode 100644 include/qemu/memfd.h
>  create mode 100644 util/memfd.c
> 
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call()
  2015-09-16 14:01   ` Michael S. Tsirkin
@ 2015-09-19  8:58     ` Marc-André Lureau
  0 siblings, 0 replies; 28+ messages in thread
From: Marc-André Lureau @ 2015-09-19  8:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Thibaut Collet, Jason Wang, Paolo Bonzini, Linhaifeng, QEMU

On Wed, Sep 16, 2015 at 4:01 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> Let's not do this.
> It's probably time to replace vhost_call with an ops struct of functions.
> This will solve this in a clean way.


done

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base
  2015-09-16 14:08   ` Michael S. Tsirkin
@ 2015-09-19  8:59     ` Marc-André Lureau
  0 siblings, 0 replies; 28+ messages in thread
From: Marc-André Lureau @ 2015-09-19  8:59 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Thibaut Collet, Jason Wang, Paolo Bonzini, Linhaifeng, QEMU

On Wed, Sep 16, 2015 at 4:08 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> supports
>

ok

>> VHOST_USER_PROTOCOL_F_LOG_SHMFD.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  hw/virtio/vhost-user.c | 16 ++++++++++++++--
>>  hw/virtio/vhost.c      |  5 +++--
>>  2 files changed, 17 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
>> index 21ecbcd..b2f46a9 100644
>> --- a/hw/virtio/vhost-user.c
>> +++ b/hw/virtio/vhost-user.c
>> @@ -26,7 +26,9 @@
>>  #define VHOST_MEMORY_MAX_NREGIONS    8
>>
>>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
>> -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
>> +
>> +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x1ULL
>> +#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 0
>>
>>  typedef enum VhostUserRequest {
>>      VHOST_USER_NONE = 0,
>> @@ -215,8 +217,18 @@ static int vhost_user_call(struct vhost_dev *dev,
>>          need_reply = 1;
>>          break;
>>
>> +    case VHOST_USER_SET_LOG_BASE: {
>> +        struct vhost_log *log = va_arg(ap, struct vhost_log *);
>> +
>> +        if (__virtio_has_feature(dev->protocol_features,
>> +                                 VHOST_USER_PROTOCOL_F_LOG_SHMFD) &&
>> +            log->fd != -1) {
>> +            fds[fd_num++] = log->fd;
>> +        }
>> +    }
>> +        /* fall through */
>> +
>
> Don't add {} like that please. Just move declarations to the top level.

Done with the vhost_call() refactoring


-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log
  2015-09-16 14:06   ` Michael S. Tsirkin
@ 2015-09-19  9:01     ` Marc-André Lureau
  0 siblings, 0 replies; 28+ messages in thread
From: Marc-André Lureau @ 2015-09-19  9:01 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Thibaut Collet, Jason Wang, Paolo Bonzini, Linhaifeng, QEMU

Hi

On Wed, Sep 16, 2015 at 4:06 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> Shouldn't this be limited to when the appropriate feature flag
> is negotiated?


That's doable, I'll add it after the feature protocol is added (not in
this commit)

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers
  2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers marcandre.lureau
@ 2015-09-29 14:57   ` Michael S. Tsirkin
  2015-09-29 15:25     ` Marc-André Lureau
  0 siblings, 1 reply; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-29 14:57 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: haifeng.lin, thibaut.collet, jasowang, qemu-devel, pbonzini

On Thu, Aug 06, 2015 at 02:40:39PM +0200, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Add qemu_memfd_alloc/free() helpers.
> 
> The function helps to allocate and seal a memfd, and implements an
> open/unlink/mmap fallback for system that do not support memfd.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/qemu/memfd.h |  4 +++
>  util/memfd.c         | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 76 insertions(+), 2 deletions(-)
> 
> diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h
> index 8b1fe6a..950fb88 100644
> --- a/include/qemu/memfd.h
> +++ b/include/qemu/memfd.h
> @@ -17,4 +17,8 @@
>  #define F_SEAL_WRITE    0x0008  /* prevent writes */
>  #endif
>  
> +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> +                       int *fd);
> +void qemu_memfd_free(void *ptr, size_t size, int fd);
> +
>  #endif /* QEMU_MEMFD_H */
> diff --git a/util/memfd.c b/util/memfd.c
> index a98d57e..8b2b785 100644
> --- a/util/memfd.c
> +++ b/util/memfd.c
> @@ -27,6 +27,14 @@
>  
>  #include "config-host.h"
>  
> +#include <glib.h>
> +#include <glib/gprintf.h>
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <sys/mman.h>
> +
>  #include "qemu/memfd.h"
>  
>  #ifdef CONFIG_MEMFD
> @@ -44,13 +52,75 @@
>  #define MFD_ALLOW_SEALING 0x0002U
>  #endif
>  
> -static inline int memfd_create(const char *name, unsigned int flags)
> +static int memfd_create(const char *name, unsigned int flags)
>  {
>      return syscall(__NR_memfd_create, name, flags);
>  }
>  #else /* !LINUX */
> -static inline int memfd_create(const char *name, unsigned int flags)
> +static int memfd_create(const char *name, unsigned int flags)
>  {
>      return -1;
>  }
>  #endif
> +
> +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> +                       int *fd)
> +{
> +    void *ptr;
> +    int mfd;
> +
> +    mfd = memfd_create(name, MFD_ALLOW_SEALING|MFD_CLOEXEC);


Hmm. Does this interact correctly with the -mem-prealloc flag?

> +    if (mfd != -1) {
> +        if (ftruncate(mfd, size) == -1) {

Any limitations on size?

> +            perror("ftruncate");
> +            close(mfd);
> +            return NULL;
> +        }
> +
> +        if (fcntl(mfd, F_ADD_SEALS, seals) == -1) {
> +            perror("fcntl");
> +            close(mfd);
> +            return NULL;
> +        }
> +    } else {
> +        const char *tmpdir = getenv("TMPDIR");
> +        gchar *fname;
> +
> +        tmpdir = tmpdir ? tmpdir : "/tmp";
> +
> +        fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir);

This means there's now work to be done to set up selinux
to allow QEMU creating memfd under /tmp.

Maybe it's better to just fail gracefully for now.

> +        mfd = mkstemp(fname);
> +        unlink(fname);
> +        g_free(fname);
> +
> +        if (mfd == -1) {
> +            perror("mkstemp");
> +            return NULL;
> +        }
> +
> +        if (ftruncate(mfd, size) == -1) {
> +            perror("ftruncate");
> +            close(mfd);
> +            return NULL;
> +        }
> +    }
> +
> +    ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);

Pls add space around | here and elsewhere.


> +    if (ptr == MAP_FAILED) {
> +        perror("mmap");
> +        close(mfd);
> +        return NULL;
> +    }
> +
> +    *fd = mfd;
> +    return ptr;
> +}
> +
> +void qemu_memfd_free(void *ptr, size_t size, int fd)
> +{
> +    if (ptr) {
> +        munmap(ptr, size);
> +    }
> +
> +    close(fd);

I notice you close fd unconditionally, but it's only returned
on success above. So this will close an uninitialized one?

> +}
> -- 
> 2.4.3

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

* Re: [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers
  2015-09-29 14:57   ` Michael S. Tsirkin
@ 2015-09-29 15:25     ` Marc-André Lureau
  2015-09-29 15:41       ` Michael S. Tsirkin
  0 siblings, 1 reply; 28+ messages in thread
From: Marc-André Lureau @ 2015-09-29 15:25 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: haifeng lin, thibaut collet, jasowang, qemu-devel, pbonzini,
	marcandre lureau



----- Original Message -----
> On Thu, Aug 06, 2015 at 02:40:39PM +0200, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > 
> > Add qemu_memfd_alloc/free() helpers.
> > 
> > The function helps to allocate and seal a memfd, and implements an
> > open/unlink/mmap fallback for system that do not support memfd.
> > 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  include/qemu/memfd.h |  4 +++
> >  util/memfd.c         | 74
> >  ++++++++++++++++++++++++++++++++++++++++++++++++++--
> >  2 files changed, 76 insertions(+), 2 deletions(-)
> > 
> > diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h
> > index 8b1fe6a..950fb88 100644
> > --- a/include/qemu/memfd.h
> > +++ b/include/qemu/memfd.h
> > @@ -17,4 +17,8 @@
> >  #define F_SEAL_WRITE    0x0008  /* prevent writes */
> >  #endif
> >  
> > +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> > +                       int *fd);
> > +void qemu_memfd_free(void *ptr, size_t size, int fd);
> > +
> >  #endif /* QEMU_MEMFD_H */
> > diff --git a/util/memfd.c b/util/memfd.c
> > index a98d57e..8b2b785 100644
> > --- a/util/memfd.c
> > +++ b/util/memfd.c
> > @@ -27,6 +27,14 @@
> >  
> >  #include "config-host.h"
> >  
> > +#include <glib.h>
> > +#include <glib/gprintf.h>
> > +
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <fcntl.h>
> > +#include <sys/mman.h>
> > +
> >  #include "qemu/memfd.h"
> >  
> >  #ifdef CONFIG_MEMFD
> > @@ -44,13 +52,75 @@
> >  #define MFD_ALLOW_SEALING 0x0002U
> >  #endif
> >  
> > -static inline int memfd_create(const char *name, unsigned int flags)
> > +static int memfd_create(const char *name, unsigned int flags)
> >  {
> >      return syscall(__NR_memfd_create, name, flags);
> >  }
> >  #else /* !LINUX */
> > -static inline int memfd_create(const char *name, unsigned int flags)
> > +static int memfd_create(const char *name, unsigned int flags)
> >  {
> >      return -1;
> >  }
> >  #endif
> > +
> > +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> > +                       int *fd)
> > +{
> > +    void *ptr;
> > +    int mfd;
> > +
> > +    mfd = memfd_create(name, MFD_ALLOW_SEALING|MFD_CLOEXEC);
> 
> 
> Hmm. Does this interact correctly with the -mem-prealloc flag?

It's unrelated imho. It's helper here.

In the rest of the series, it's used at runtime when migrating with variable size (today code doesn't prealloc that either)

> 
> > +    if (mfd != -1) {
> > +        if (ftruncate(mfd, size) == -1) {
> 
> Any limitations on size?

not that I know (reading memfd_create)

> 
> > +            perror("ftruncate");
> > +            close(mfd);
> > +            return NULL;
> > +        }
> > +
> > +        if (fcntl(mfd, F_ADD_SEALS, seals) == -1) {
> > +            perror("fcntl");
> > +            close(mfd);
> > +            return NULL;
> > +        }
> > +    } else {
> > +        const char *tmpdir = getenv("TMPDIR");
> > +        gchar *fname;
> > +
> > +        tmpdir = tmpdir ? tmpdir : "/tmp";
> > +
> > +        fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir);
> 
> This means there's now work to be done to set up selinux
> to allow QEMU creating memfd under /tmp.

doesn't sound unreasonable to me

> 
> Maybe it's better to just fail gracefully for now.

it's a fallback, but sure we can remove it and add it back later if needed

> > +        mfd = mkstemp(fname);
> > +        unlink(fname);
> > +        g_free(fname);
> > +
> > +        if (mfd == -1) {
> > +            perror("mkstemp");
> > +            return NULL;
> > +        }
> > +
> > +        if (ftruncate(mfd, size) == -1) {
> > +            perror("ftruncate");
> > +            close(mfd);
> > +            return NULL;
> > +        }
> > +    }
> > +
> > +    ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
> 
> Pls add space around | here and elsewhere.
> 

ok
> 
> > +    if (ptr == MAP_FAILED) {
> > +        perror("mmap");
> > +        close(mfd);
> > +        return NULL;
> > +    }
> > +
> > +    *fd = mfd;
> > +    return ptr;
> > +}
> > +
> > +void qemu_memfd_free(void *ptr, size_t size, int fd)
> > +{
> > +    if (ptr) {
> > +        munmap(ptr, size);
> > +    }
> > +
> > +    close(fd);
> 
> I notice you close fd unconditionally, but it's only returned
> on success above. So this will close an uninitialized one?

Ok, I'll add a -1 check

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

* Re: [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers
  2015-09-29 15:25     ` Marc-André Lureau
@ 2015-09-29 15:41       ` Michael S. Tsirkin
  0 siblings, 0 replies; 28+ messages in thread
From: Michael S. Tsirkin @ 2015-09-29 15:41 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: haifeng lin, thibaut collet, jasowang, qemu-devel, pbonzini,
	marcandre lureau

On Tue, Sep 29, 2015 at 11:25:04AM -0400, Marc-André Lureau wrote:
> 
> 
> ----- Original Message -----
> > On Thu, Aug 06, 2015 at 02:40:39PM +0200, marcandre.lureau@redhat.com wrote:
> > > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > 
> > > Add qemu_memfd_alloc/free() helpers.
> > > 
> > > The function helps to allocate and seal a memfd, and implements an
> > > open/unlink/mmap fallback for system that do not support memfd.
> > > 
> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > ---
> > >  include/qemu/memfd.h |  4 +++
> > >  util/memfd.c         | 74
> > >  ++++++++++++++++++++++++++++++++++++++++++++++++++--
> > >  2 files changed, 76 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h
> > > index 8b1fe6a..950fb88 100644
> > > --- a/include/qemu/memfd.h
> > > +++ b/include/qemu/memfd.h
> > > @@ -17,4 +17,8 @@
> > >  #define F_SEAL_WRITE    0x0008  /* prevent writes */
> > >  #endif
> > >  
> > > +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> > > +                       int *fd);
> > > +void qemu_memfd_free(void *ptr, size_t size, int fd);
> > > +
> > >  #endif /* QEMU_MEMFD_H */
> > > diff --git a/util/memfd.c b/util/memfd.c
> > > index a98d57e..8b2b785 100644
> > > --- a/util/memfd.c
> > > +++ b/util/memfd.c
> > > @@ -27,6 +27,14 @@
> > >  
> > >  #include "config-host.h"
> > >  
> > > +#include <glib.h>
> > > +#include <glib/gprintf.h>
> > > +
> > > +#include <stdio.h>
> > > +#include <stdlib.h>
> > > +#include <fcntl.h>
> > > +#include <sys/mman.h>
> > > +
> > >  #include "qemu/memfd.h"
> > >  
> > >  #ifdef CONFIG_MEMFD
> > > @@ -44,13 +52,75 @@
> > >  #define MFD_ALLOW_SEALING 0x0002U
> > >  #endif
> > >  
> > > -static inline int memfd_create(const char *name, unsigned int flags)
> > > +static int memfd_create(const char *name, unsigned int flags)
> > >  {
> > >      return syscall(__NR_memfd_create, name, flags);
> > >  }
> > >  #else /* !LINUX */
> > > -static inline int memfd_create(const char *name, unsigned int flags)
> > > +static int memfd_create(const char *name, unsigned int flags)
> > >  {
> > >      return -1;
> > >  }
> > >  #endif
> > > +
> > > +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
> > > +                       int *fd)
> > > +{
> > > +    void *ptr;
> > > +    int mfd;
> > > +
> > > +    mfd = memfd_create(name, MFD_ALLOW_SEALING|MFD_CLOEXEC);
> > 
> > 
> > Hmm. Does this interact correctly with the -mem-prealloc flag?
> 
> It's unrelated imho. It's helper here.
> 
> In the rest of the series, it's used at runtime when migrating with variable size (today code doesn't prealloc that either)

Yes but I think this means it will fault on access even if user
requested -realtime mlock=on.

> > 
> > > +    if (mfd != -1) {
> > > +        if (ftruncate(mfd, size) == -1) {
> > 
> > Any limitations on size?
> 
> not that I know (reading memfd_create)
> 
> > 
> > > +            perror("ftruncate");
> > > +            close(mfd);
> > > +            return NULL;
> > > +        }
> > > +
> > > +        if (fcntl(mfd, F_ADD_SEALS, seals) == -1) {
> > > +            perror("fcntl");
> > > +            close(mfd);
> > > +            return NULL;
> > > +        }
> > > +    } else {
> > > +        const char *tmpdir = getenv("TMPDIR");
> > > +        gchar *fname;
> > > +
> > > +        tmpdir = tmpdir ? tmpdir : "/tmp";
> > > +
> > > +        fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir);
> > 
> > This means there's now work to be done to set up selinux
> > to allow QEMU creating memfd under /tmp.
> 
> doesn't sound unreasonable to me
> 
> > 
> > Maybe it's better to just fail gracefully for now.
> 
> it's a fallback, but sure we can remove it and add it back later if needed
> 
> > > +        mfd = mkstemp(fname);
> > > +        unlink(fname);
> > > +        g_free(fname);
> > > +
> > > +        if (mfd == -1) {
> > > +            perror("mkstemp");
> > > +            return NULL;
> > > +        }
> > > +
> > > +        if (ftruncate(mfd, size) == -1) {
> > > +            perror("ftruncate");
> > > +            close(mfd);
> > > +            return NULL;
> > > +        }
> > > +    }
> > > +
> > > +    ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
> > 
> > Pls add space around | here and elsewhere.
> > 
> 
> ok
> > 
> > > +    if (ptr == MAP_FAILED) {
> > > +        perror("mmap");
> > > +        close(mfd);
> > > +        return NULL;
> > > +    }
> > > +
> > > +    *fd = mfd;
> > > +    return ptr;
> > > +}
> > > +
> > > +void qemu_memfd_free(void *ptr, size_t size, int fd)
> > > +{
> > > +    if (ptr) {
> > > +        munmap(ptr, size);
> > > +    }
> > > +
> > > +    close(fd);
> > 
> > I notice you close fd unconditionally, but it's only returned
> > on success above. So this will close an uninitialized one?
> 
> Ok, I'll add a -1 check

Will only work well if you set *fd to -1 on error above ...

-- 
MST

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

end of thread, other threads:[~2015-09-29 15:41 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-06 12:40 [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 01/16] configure: probe for memfd marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 02/16] util: add linux-only memfd fallback marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 03/16] util: add memfd helpers marcandre.lureau
2015-09-29 14:57   ` Michael S. Tsirkin
2015-09-29 15:25     ` Marc-André Lureau
2015-09-29 15:41       ` Michael S. Tsirkin
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 04/16] vhost: alloc shareable log marcandre.lureau
2015-09-16 14:06   ` Michael S. Tsirkin
2015-09-19  9:01     ` Marc-André Lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 05/16] vhost: document log resizing marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 06/16] vhost: use variable arguments for vhost_call() marcandre.lureau
2015-09-16 14:01   ` Michael S. Tsirkin
2015-09-19  8:58     ` Marc-André Lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 07/16] vhost-user: start and end the va_list marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 08/16] vhost-user: send log shm fd along with log_base marcandre.lureau
2015-09-16 14:08   ` Michael S. Tsirkin
2015-09-19  8:59     ` Marc-André Lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 09/16] vhost-user: document migration log marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 10/16] net: add trace_vhost_user_event marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 11/16] vhost-user-test: move wait_for_fds() out marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 12/16] vhost-user-test: remove useless static check marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 13/16] vhost-user-test: wrap server in TestServer struct marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 14/16] vhost-user-test: learn to tweak various qemu arguments marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 15/16] vhost-user-test: add live-migration test marcandre.lureau
2015-08-06 12:40 ` [Qemu-devel] [PATCH v3 16/16] vhost-user-test: check ownership during migration marcandre.lureau
2015-09-16 14:02 ` [Qemu-devel] [PATCH v3 00/16] vhost-user: add migration log support (for 2.5) Michael S. Tsirkin
2015-09-16 14:46 ` Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).