[libvirt] [PATCH v1 6/6] ivshmem: add start param to server attribute

Maxime Leroy maxime.leroy at 6wind.com
Fri Aug 22 10:47:05 UTC 2014


With the new start param, we are able to start the
ivshmem-server.

With this xml:

  <shmem name='ivshmem0' model='ivshmem'>
     <server path='/tmp/ivshmem0.sock' start='yes'/>
     <size unit='M'>32</size>
     <msi vectors='32' ioeventfd='on'/>
  </shmem>

Libvirt will execute an ivshmem-server:

  /usr/bin/ivshmem-server -m ivshmem0 -S /tmp/ivshmem0.sock  \
    -p /var/run/libvirt/ivshmem-server/ivshd-ivshmem0.pid  -n 32

Signed-off-by: Maxime Leroy <maxime.leroy at 6wind.com>
---
 configure.ac                                    |   4 +
 docs/formatdomain.html.in                       |   5 +-
 docs/schemas/domaincommon.rng                   |   3 +
 po/POTFILES.in                                  |   1 +
 src/Makefile.am                                 |   1 +
 src/conf/domain_conf.c                          |  19 +++-
 src/conf/domain_conf.h                          |   1 +
 src/libvirt_private.syms                        |   5 +
 src/qemu/qemu_command.c                         |   7 ++
 src/qemu/qemu_process.c                         |  10 ++
 src/util/virivshmemserver.c                     | 141 ++++++++++++++++++++++++
 src/util/virivshmemserver.h                     |  28 +++++
 tests/qemuxml2argvdata/qemuxml2argv-ivshmem.xml |   2 +-
 13 files changed, 223 insertions(+), 4 deletions(-)
 create mode 100644 src/util/virivshmemserver.c
 create mode 100644 src/util/virivshmemserver.h

diff --git a/configure.ac b/configure.ac
index f93c6c2..6b525b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -431,6 +431,8 @@ AC_PATH_PROG([SCRUB], [scrub], [scrub],
 	[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
 AC_PATH_PROG([ADDR2LINE], [addr2line], [addr2line],
         [/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:$PATH])
+AC_PATH_PROG([IVSHMEMSERVER], [ivshmem-server], [ivshmem-server],
+	[/usr/bin:/usr/local/bin:$PATH])
 
 AC_DEFINE_UNQUOTED([DMIDECODE],["$DMIDECODE"],
         [Location or name of the dmidecode program])
@@ -463,6 +465,8 @@ AC_DEFINE_UNQUOTED([SCRUB],["$SCRUB"],
         [Location or name of the scrub program (for wiping algorithms)])
 AC_DEFINE_UNQUOTED([ADDR2LINE],["$ADDR2LINE"],
         [Location of addr2line program])
+AC_DEFINE_UNQUOTED([IVSHMEMSERVER], ["$IVSHMEMSERVER"],
+	[Location or name of ivshmem-server program])
 
 dnl Specific dir for HTML output ?
 AC_ARG_WITH([html-dir], [AS_HELP_STRING([--with-html-dir=path],
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index c7644bc..df231d8 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5462,7 +5462,7 @@ qemu-kvm -net nic,model=? /dev/null
   ...
   <devices>
     <shmem name='shmem0' model='ivshmem'>
-      <server path='/tmp/socket-shmem0'/>
+      <server path='/tmp/socket-shmem0' start='yes'/>
       <size unit='M'>32</size>
       <msi vectors='32' ioeventfd='on'/>
     </shmem>
@@ -5477,6 +5477,9 @@ qemu-kvm -net nic,model=? /dev/null
     <dd>The optional <code>server</code> element can be used to configure an
       ivshmem device connected to the ivshmem server via a unix socket. The
       <code>path</code> attribute specifies the path to the unix socket.
+      The <code>start</code> attribute specifies if the libvirt must start
+      the ivshmem-server. By default, libvirt expects that the ivshmem-server is
+      already running on the host.
     </dd>
     <dt><code>size</code></dt>
     <dd>The optional <code>size</code> element specifies the size of the shared memory.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 64abf2b..a601747 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3246,6 +3246,9 @@
        <optional>
          <element name="server">
            <attribute name="path"/>
+         <optional>
+           <attribute name="start"/>
+         </optional>
          </element>
        </optional>
        <optional>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f17b35f..7d90517 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -177,6 +177,7 @@ src/util/viridentity.c
 src/util/virinitctl.c
 src/util/viriptables.c
 src/util/viriscsi.c
+src/util/virivshmemserver.c
 src/util/virjson.c
 src/util/virkeyfile.c
 src/util/virlockspace.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 538530e..00e1ccf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -118,6 +118,7 @@ UTIL_SOURCES =							\
 		util/virinitctl.c util/virinitctl.h		\
 		util/viriptables.c util/viriptables.h		\
 		util/viriscsi.c util/viriscsi.h			\
+		util/virivshmemserver.c util/virivshmemserver.h	\
 		util/virjson.c util/virjson.h			\
 		util/virkeycode.c util/virkeycode.h		\
 		util/virkeyfile.c util/virkeyfile.h		\
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 08d653a..224b367 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9509,6 +9509,7 @@ virDomainIvshmemDefParseXML(xmlNodePtr node,
 {
     char *ioeventfd = NULL;
     char *vectors = NULL;
+    char *start = NULL;
     xmlNodePtr cur;
     xmlNodePtr save = ctxt->node;
     int ret;
@@ -9523,6 +9524,13 @@ virDomainIvshmemDefParseXML(xmlNodePtr node,
                                    _("cannot parse <server> 'path' attribute"));
                     goto error;
                 }
+                start = virXMLPropString(cur, "start");
+                if (start &&
+                    (def->server.start = virTristateBoolTypeFromString(start)) <= 0) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("unknown <start> value '%s'"),
+                                   start);
+                }
             } else if (xmlStrEqual(cur->name, BAD_CAST "size")) {
                 if (virDomainParseScaledValue("./size[1]", ctxt,
                                               &def->size, 1,
@@ -9575,6 +9583,7 @@ virDomainIvshmemDefParseXML(xmlNodePtr node,
     ctxt->node = save;
     VIR_FREE(ioeventfd);
     VIR_FREE(vectors);
+    VIR_FREE(start);
     return ret;
 
  error:
@@ -17023,9 +17032,15 @@ static int virDomainPanicDefFormat(virBufferPtr buf,
 static int virDomainIvshmemDefFormat(virBufferPtr buf,
                                      virDomainIvshmemDefPtr def)
 {
-    if (def->server.enabled)
-        virBufferAsprintf(buf, "<server path='%s'/>\n",
+    if (def->server.enabled) {
+        virBufferAsprintf(buf, "<server path='%s'",
                           def->server.path);
+        if (def->server.start)
+            virBufferAsprintf(buf, " start='%s'",
+                              virTristateBoolTypeToString(def->server.start));
+        virBufferAddLit(buf, "/>\n");
+    }
+
     if (def->size)
         virBufferAsprintf(buf, "<size unit='M'>%llu</size>\n",
                           def->size  / (1024 * 1024));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0c6aa21..7c01c22 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1504,6 +1504,7 @@ struct _virDomainIvshmemDef {
     unsigned long long size;
     struct {
         bool enabled;
+        int start; /* enum virTristateBool */
         char *path;
     } server;
     struct {
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f86926e..ee77995 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1440,6 +1440,11 @@ virISCSIRescanLUNs;
 virISCSIScanTargets;
 
 
+# util/virivshmemserver.h
+virStartIvshmemServer;
+virStopIvshmemServer;
+
+
 # util/virjson.h
 virJSONValueArrayAppend;
 virJSONValueArrayGet;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9fcceae..fe2fc1a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -34,6 +34,7 @@
 #include "virarch.h"
 #include "virerror.h"
 #include "virfile.h"
+#include "virivshmemserver.h"
 #include "virnetdev.h"
 #include "virstring.h"
 #include "virtime.h"
@@ -5120,6 +5121,12 @@ qemuBuildIvshmemCommandLine(virCommandPtr cmd,
                 return -1;
             virCommandAddArg(cmd, devstr);
             VIR_FREE(devstr);
+
+            if (ivshmem->server.start == VIR_TRISTATE_BOOL_YES) {
+                if (virStartIvshmemServer(dev->name, ivshmem->server.path,
+                                          ivshmem->size, ivshmem->msi.vectors))
+                    return -1;
+            }
     }
 
     return 0;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index baa866a..aaf03a3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -67,6 +67,7 @@
 #include "virstring.h"
 #include "virhostdev.h"
 #include "storage/storage_driver.h"
+#include "virivshmemserver.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -4684,6 +4685,15 @@ void qemuProcessStop(virQEMUDriverPtr driver,
         }
     }
 
+    /* stop runnning ivshmem server */
+    for (i = 0; i < vm->def->nshmems; i++) {
+        virDomainShmemDefPtr shmem =  vm->def->shmems[i];
+        if (shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM &&
+            shmem->data.ivshmem.server.start == VIR_TRISTATE_BOOL_YES) {
+            virStopIvshmemServer(shmem->name);
+        }
+    }
+
     vm->taint = 0;
     vm->pid = -1;
     virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
diff --git a/src/util/virivshmemserver.c b/src/util/virivshmemserver.c
new file mode 100644
index 0000000..89130b1
--- /dev/null
+++ b/src/util/virivshmemserver.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014 6WIND S.A.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include <string.h>
+#include <signal.h>
+
+#include "virivshmemserver.h"
+#include "vircommand.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virlog.h"
+#include "virstring.h"
+#include "virfile.h"
+#include "virpidfile.h"
+#include "virprocess.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.ivshmemserver")
+
+#define IVSHMEM_STATE_DIR LOCALSTATEDIR "/run/libvirt/ivshmem-server"
+
+static char *virIvshmemServerPidFileBasename(const char *shm_name) {
+    char *pidfilebase;
+
+    ignore_value(virAsprintf(&pidfilebase, "ivshd-%s",  shm_name));
+    return pidfilebase;
+}
+
+/**
+ * virStartIvshmemServer:
+ * @shm_name: the name of the shared memory
+ * @unix_socket_path: the path to the socket unix file
+ * @size: the size of the shared memory (optionnal)
+ * @vectors: the number of vectors (optionnal)
+ *
+ * Start an Ivshmem Server
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int
+virStartIvshmemServer(const char *shm_name, const char *unix_socket_path,
+                      size_t size, unsigned vectors)
+{
+    char *ivshmserver_pidbase = NULL;
+    char *pidfile = NULL;
+    virCommandPtr cmd = NULL;
+    int ret = -1;
+
+    if (!virFileIsExecutable(IVSHMEMSERVER)) {
+        virReportSystemError(errno, _(" %s is not available"),
+                             IVSHMEMSERVER);
+        goto cleanup;
+    }
+
+    if (virFileMakePath(IVSHMEM_STATE_DIR) < 0) {
+        virReportSystemError(errno,
+                             _("cannot create directory %s"),
+                             IVSHMEM_STATE_DIR);
+        goto cleanup;
+    }
+
+    /* construct pidfile name */
+    if (!(ivshmserver_pidbase = virIvshmemServerPidFileBasename(shm_name)))
+        goto cleanup;
+    if (!(pidfile = virPidFileBuildPath(IVSHMEM_STATE_DIR, ivshmserver_pidbase)))
+        goto cleanup;
+
+    cmd = virCommandNewArgList(IVSHMEMSERVER, "-m", shm_name,
+                               "-S", unix_socket_path, "-p", pidfile, NULL);
+
+    if (size)
+        virCommandAddArgFormat(cmd, "-l %zu", size);
+
+    if (vectors)
+        virCommandAddArgFormat(cmd, "-n %u", vectors);
+
+    virCommandSetPidFile(cmd, pidfile);
+    virCommandDaemonize(cmd);
+
+    if (virCommandRun(cmd, NULL) < 0) {
+        virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+                             _("Unable to start %s for %s shm"),
+                             IVSHMEMSERVER, shm_name);
+        goto cleanup;
+    }
+    ret = 0;
+ cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(ivshmserver_pidbase);
+    VIR_FREE(pidfile);
+    return ret;
+}
+
+/**
+ * virStopIvshmemServer:
+ * @shm_name: the name of the shared memory
+ *
+ * Stop an Ivshmem Server
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int
+virStopIvshmemServer(const char *shm_name)
+{
+    char *ivshmserver_pidbase = NULL;
+    pid_t ivshmserver_pid;
+    int ret = -1;
+
+    /* get pid of the ivshmem server */
+    if (!(ivshmserver_pidbase = virIvshmemServerPidFileBasename(shm_name)))
+        goto cleanup;
+    if (virPidFileRead(IVSHMEM_STATE_DIR, ivshmserver_pidbase,
+                        &ivshmserver_pid))
+        goto cleanup;
+
+    virProcessKill(ivshmserver_pid, SIGTERM);
+    virPidFileDelete(IVSHMEM_STATE_DIR, ivshmserver_pidbase);
+    ret = 0;
+ cleanup:
+    VIR_FREE(ivshmserver_pidbase);
+    return ret;
+}
diff --git a/src/util/virivshmemserver.h b/src/util/virivshmemserver.h
new file mode 100644
index 0000000..1fae8d9
--- /dev/null
+++ b/src/util/virivshmemserver.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2014 6WIND S.A.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __VIR_IVSHMEM_SERVER_H__
+# define __VIR_IVSHMEN_SERVER_H__
+
+int virStartIvshmemServer(const char *shm_name, const char *unix_socket_path,
+                          size_t size, unsigned vectors);
+
+int virStopIvshmemServer(const char *shm_name);
+
+#endif /*  __VIR_IVSHMEM_SERVER_H__ */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-ivshmem.xml b/tests/qemuxml2argvdata/qemuxml2argv-ivshmem.xml
index 7177612..22c1d14 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-ivshmem.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-ivshmem.xml
@@ -19,7 +19,7 @@
     <controller type='pci' index='0' model='pci-root'/>
     <memballoon model='virtio'/>
     <shmem name='shmem0' model='ivshmem'>
-      <server path='/tmp/socket-shmem0'/>
+      <server path='/tmp/socket-shmem0' start='no'/>
       <msi vectors='32' ioeventfd='on'/>
     </shmem>
     <shmem name='shmem1' model='ivshmem'>
-- 
1.9.3




More information about the libvir-list mailing list