[libvirt] [PATCH 8/9] wip: start virtiofsd

Ján Tomko jtomko at redhat.com
Fri Nov 1 12:16:06 UTC 2019


Start virtiofsd for each <filesystem> device using it.

Pre-create the socket for communication with QEMU and pass it
to virtiofsd.

Note that virtiofsd needs to run as root.
---
 src/conf/domain_conf.h    |   1 +
 src/qemu/qemu_extdevice.c | 191 ++++++++++++++++++++++++++++++++++++++
 tests/qemuxml2argvtest.c  |   6 ++
 3 files changed, 198 insertions(+)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 54a7e7c52f..78f88a0c2f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -817,6 +817,7 @@ struct _virDomainFSDef {
     unsigned long long space_soft_limit; /* in bytes */
     bool symlinksResolved;
     virDomainVirtioOptionsPtr virtio;
+    char *vhost_user_fs_path; /* TODO put this in private data */
 };
 
 
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 463f76c21a..cb44ca325f 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -20,6 +20,7 @@
 
 #include <config.h>
 
+#include "qemu_command.h"
 #include "qemu_extdevice.h"
 #include "qemu_vhost_user_gpu.h"
 #include "qemu_domain.h"
@@ -149,6 +150,178 @@ qemuExtDevicesCleanupHost(virQEMUDriverPtr driver,
         qemuExtTPMCleanupHost(def);
 }
 
+static char *
+qemuExtVirtioFSCreatePidFilename(virQEMUDriverConfigPtr cfg,
+                                 const virDomainDef *def,
+                                 const char *alias)
+{
+    g_autofree char *shortName = NULL;
+    g_autofree char *name = NULL;
+
+    if (!(shortName = virDomainDefGetShortName(def)) ||
+        virAsprintf(&name, "%s-%s-virtiofsd", shortName, alias) < 0)
+        return NULL;
+
+    return virPidFileBuildPath(cfg->stateDir, name);
+}
+
+
+static char *
+qemuExtVirtioFSCreateSocketFilename(virQEMUDriverConfigPtr cfg,
+                                    const virDomainDef *def,
+                                    const char *alias)
+{
+    g_autofree char *shortName = NULL;
+    g_autofree char *name = NULL;
+
+    if (!(shortName = virDomainDefGetShortName(def)) ||
+        virAsprintf(&name, "%s-%s-virtiofsd", shortName, alias) < 0)
+        return NULL;
+
+    return virFileBuildPath(cfg->stateDir, name, ".sock");
+}
+
+
+static int
+qemuExtVirtioFSdStart(virQEMUDriverPtr driver,
+                      virDomainObjPtr vm,
+                      virDomainFSDefPtr fs)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    g_autoptr(virCommand) cmd = NULL;
+    g_autofree char *pidfile = NULL;
+    char errbuf[1024] = { 0 };
+    virDomainChrSourceDefPtr chrdev = virDomainChrSourceDefNew(NULL);
+    pid_t pid = (pid_t) -1;
+    VIR_AUTOCLOSE errfd = -1;
+    VIR_AUTOCLOSE fd = -1;
+    int exitstatus = 0;
+    int cmdret = 0;
+    int ret = -1;
+    int rc;
+
+    chrdev->type = VIR_DOMAIN_CHR_TYPE_UNIX;
+    chrdev->data.nix.listen = true;
+
+    if (!(pidfile = qemuExtVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias)))
+        goto cleanup;
+
+    if (!(chrdev->data.nix.path = qemuExtVirtioFSCreateSocketFilename(cfg, vm->def, fs->info.alias)))
+        goto cleanup;
+
+    if (qemuSecuritySetDaemonSocketLabel(driver->securityManager, vm->def) < 0)
+        goto cleanup;
+    fd = qemuOpenChrChardevUNIXSocket(chrdev);
+    if (fd < 0)
+        goto cleanup;
+    if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0)
+        goto cleanup;
+
+    /* TODO: do not call this here */
+    virDomainChrDef chr = { .source = chrdev };
+    if (qemuSecuritySetChardevLabel(driver, vm, &chr) < 0)
+        goto cleanup;
+
+    /* TODO: configure path */
+    if (!(cmd = virCommandNew("/usr/libexec/virtiofsd")))
+        goto cleanup;
+
+    virCommandSetPidFile(cmd, pidfile);
+    virCommandSetErrorFD(cmd, &errfd);
+    virCommandDaemonize(cmd);
+
+    virCommandAddArg(cmd, "--syslog");
+    virCommandAddArgFormat(cmd, "--fd=%d", fd);
+    virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+    fd = -1;
+
+    virCommandAddArg(cmd, "-o");
+    /* TODO: validate path? */
+    virCommandAddArgFormat(cmd, "source=%s", fs->src->path);
+    virCommandAddArg(cmd, "-d");
+
+    if (qemuExtDeviceLogCommand(driver, vm, cmd, "virtiofsd") < 0)
+        goto cleanup;
+
+    cmdret = virCommandRun(cmd, &exitstatus);
+
+    if (cmdret < 0 || exitstatus != 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not start 'virtiofsd'. exitstatus: %d"), exitstatus);
+        goto error;
+    }
+
+    rc = virPidFileReadPath(pidfile, &pid);
+    if (rc < 0) {
+        virReportSystemError(-rc,
+                             _("Unable to read virtiofsd pidfile '%s'"),
+                             pidfile);
+        goto error;
+    }
+
+    if (virProcessKill(pid, 0) != 0) {
+        if (saferead(errfd, errbuf, sizeof(errbuf) - 1) < 0) {
+            virReportSystemError(errno, "%s",
+                                 _("virtiofsd died unexpectedly"));
+        } else {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("virtiofsd died and reported: %s"), errbuf);
+        }
+        goto error;
+    }
+
+    fs->vhost_user_fs_path = g_steal_pointer(&chrdev->data.nix.path);
+    ret = 0;
+
+ cleanup:
+    if (chrdev->data.nix.path)
+        unlink(chrdev->data.nix.path);
+    virObjectUnref(chrdev);
+    return ret;
+
+ error:
+    if (pid != -1)
+        virProcessKillPainfully(pid, true);
+    if (pidfile)
+        unlink(pidfile);
+    goto cleanup;
+}
+
+
+static void
+qemuExtVirtioFSdStop(virQEMUDriverPtr driver,
+                     virDomainObjPtr vm,
+                     virDomainFSDefPtr fs)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    g_autofree char *pidfile = NULL;
+    virErrorPtr orig_err;
+    pid_t pid = -1;
+    int rc;
+
+    virErrorPreserveLast(&orig_err);
+
+    if (!(pidfile = qemuExtVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias)))
+        goto cleanup;
+
+    rc = virPidFileReadPathIfAlive(pidfile, &pid, NULL);
+    if (rc >= 0 && pid != (pid_t) -1)
+        virProcessKillPainfully(pid, true);
+
+    if (unlink(pidfile) < 0 &&
+        errno != ENOENT) {
+        virReportSystemError(errno,
+                             _("Unable to remove stale pidfile %s"),
+                             pidfile);
+    }
+
+    if (fs->vhost_user_fs_path)
+        unlink(fs->vhost_user_fs_path);
+
+ cleanup:
+    virErrorRestore(&orig_err);
+}
+
 
 int
 qemuExtDevicesStart(virQEMUDriverPtr driver,
@@ -184,6 +357,17 @@ qemuExtDevicesStart(virQEMUDriverPtr driver,
             return -1;
     }
 
+    for (i = 0; i < def->nfss; i++) {
+        /* FIXME: use private data */
+        virDomainFSDefPtr fs = def->fss[i];
+
+        if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIO_FS) {
+            if (qemuExtVirtioFSdStart(driver, vm, fs) < 0)
+                return -1;
+        }
+    }
+
+
     return ret;
 }
 
@@ -215,6 +399,13 @@ qemuExtDevicesStop(virQEMUDriverPtr driver,
         if (slirp)
             qemuSlirpStop(slirp, vm, driver, net, false);
     }
+
+    for (i = 0; i < def->nfss; i++) {
+        virDomainFSDefPtr fs = def->fss[i];
+
+        if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIO_FS)
+            qemuExtVirtioFSdStop(driver, vm, fs);
+    }
 }
 
 
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 24df0a48e7..bf3366f953 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -501,6 +501,12 @@ testCompareXMLToArgv(const void *data)
         }
     }
 
+    for (i = 0; i < vm->def->nfss; i++) {
+        virDomainFSDefPtr fs = vm->def->fss[i];
+        char *s = g_strdup_printf("/tmp/lib/domain--1-guest/fs%zu.vhost-fs.sock", i);
+        fs->vhost_user_fs_path = s;
+    }
+
     if (vm->def->vsock) {
         virDomainVsockDefPtr vsock = vm->def->vsock;
         qemuDomainVsockPrivatePtr vsockPriv =
-- 
2.21.0




More information about the libvir-list mailing list