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(a)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