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@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list