[libvirt PATCH v4 08/31] qemu: Add qemuNbdkitProcess

Jonathon Jongsma jjongsma at redhat.com
Fri Jan 20 22:03:02 UTC 2023


An object for storing information about a nbdkit process that is serving
a specific virStorageSource. At the moment, this information is just
stored in the private data of virStorageSource and not used at all.
Future commits will use this data to actually start a nbdkit process.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 src/qemu/qemu_conf.c   | 22 ++++++++++++
 src/qemu/qemu_conf.h   |  2 ++
 src/qemu/qemu_domain.c | 31 ++++++++++++++++
 src/qemu/qemu_domain.h |  4 +++
 src/qemu/qemu_nbdkit.c | 82 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_nbdkit.h | 26 ++++++++++++++
 6 files changed, 167 insertions(+)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 16d52cbbd4..f47c70985f 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1669,3 +1669,25 @@ qemuHugepageMakeBasedir(virQEMUDriver *driver,
 
     return 0;
 }
+
+
+/*
+ * qemuGetNbdkitCaps:
+ * @driver: the qemu driver
+ *
+ * Gets the capabilities for Nbdkit for the specified driver. These can be used
+ * to determine whether a particular disk source can be served by nbdkit or
+ * not.
+ *
+ * Returns: a reference to qemuNbdkitCaps or NULL
+ */
+qemuNbdkitCaps*
+qemuGetNbdkitCaps(virQEMUDriver *driver)
+{
+    char *nbdkitBinary = virFindFileInPath("nbdkit");
+
+    if (!nbdkitBinary)
+        return NULL;
+
+    return virFileCacheLookup(driver->nbdkitCapsCache, nbdkitBinary);
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index a44985fb8b..1a3ba3a0fb 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -377,3 +377,5 @@ int qemuGetMemoryBackingPath(virQEMUDriver *driver,
 
 int qemuHugepageMakeBasedir(virQEMUDriver *driver,
                             virHugeTLBFS *hugepage);
+
+qemuNbdkitCaps* qemuGetNbdkitCaps(virQEMUDriver *driver);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 2eb5653254..bcf051d6b1 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -875,6 +875,7 @@ qemuDomainStorageSourcePrivateDispose(void *obj)
     g_clear_pointer(&priv->httpcookie, qemuDomainSecretInfoFree);
     g_clear_pointer(&priv->tlsKeySecret, qemuDomainSecretInfoFree);
     g_clear_pointer(&priv->fdpass, qemuFDPassFree);
+    g_clear_pointer(&priv->nbdkitProcess, qemuNbdkitProcessFree);
 }
 
 
@@ -10097,6 +10098,34 @@ qemuDomainPrepareStorageSourceNFS(virStorageSource *src)
 }
 
 
+/* qemuPrepareStorageSourceNbdkit:
+ * @src: source for a disk
+ *
+ * If src is an network source that is managed by nbdkit, prepare data so that
+ * nbdkit can be launched before the domain is started
+ *
+ * Returns true if nbdkit will be used for this source,
+ */
+static bool
+qemuDomainPrepareStorageSourceNbdkit(virStorageSource *src,
+                                     virQEMUDriverConfig *cfg,
+                                     const char *alias,
+                                     qemuDomainObjPrivate *priv)
+{
+    g_autoptr(qemuNbdkitCaps) nbdkit = NULL;
+
+    if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK)
+        return false;
+
+    nbdkit = qemuGetNbdkitCaps(priv->driver);
+    if (!nbdkit)
+        return false;
+
+    return qemuNbdkitInitStorageSource(nbdkit, src, priv->libDir,
+                                       alias, cfg->user, cfg->group);
+}
+
+
 /* qemuProcessPrepareStorageSourceTLS:
  * @source: source for a disk
  * @cfg: driver configuration
@@ -10929,6 +10958,8 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
     if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0)
         return -1;
 
+    qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, priv);
+
     return 0;
 }
 
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 08430b67b9..a3b9acab70 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -33,6 +33,7 @@
 #include "qemu_conf.h"
 #include "qemu_capabilities.h"
 #include "qemu_migration_params.h"
+#include "qemu_nbdkit.h"
 #include "qemu_slirp.h"
 #include "qemu_fd.h"
 #include "virchrdev.h"
@@ -308,6 +309,9 @@ struct _qemuDomainStorageSourcePrivate {
 
     /* file descriptors if user asks for FDs to be passed */
     qemuFDPass *fdpass;
+
+    /* an nbdkit process for serving network storage sources */
+    qemuNbdkitProcess *nbdkitProcess;
 };
 
 virObject *qemuDomainStorageSourcePrivateNew(void);
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
index 82586379d0..231908b6b1 100644
--- a/src/qemu/qemu_nbdkit.c
+++ b/src/qemu/qemu_nbdkit.c
@@ -548,3 +548,85 @@ qemuNbdkitCapsCacheNew(const char *cachedir)
     g_autofree char *dir = g_build_filename(cachedir, "nbdkitcapabilities", NULL);
     return virFileCacheNew(dir, "xml", &nbdkitCapsCacheHandlers);
 }
+
+
+static qemuNbdkitProcess *
+qemuNbdkitProcessNew(virStorageSource *source,
+                     const char *pidfile,
+                     const char *socketfile)
+{
+    qemuNbdkitProcess *nbdkit = g_new0(qemuNbdkitProcess, 1);
+    /* weak reference -- source owns this object, so it will always outlive us */
+    nbdkit->source = source;
+    nbdkit->user = -1;
+    nbdkit->group = -1;
+    nbdkit->pid = -1;
+    nbdkit->pidfile = g_strdup(pidfile);
+    nbdkit->socketfile = g_strdup(socketfile);
+
+    return nbdkit;
+}
+
+
+bool
+qemuNbdkitInitStorageSource(qemuNbdkitCaps *caps,
+                            virStorageSource *source,
+                            char *statedir,
+                            const char *alias,
+                            uid_t user,
+                            gid_t group)
+{
+    qemuDomainStorageSourcePrivate *srcPriv = qemuDomainStorageSourcePrivateFetch(source);
+    g_autofree char *pidname = g_strdup_printf("nbdkit-%s.pid", alias);
+    g_autofree char *socketname = g_strdup_printf("nbdkit-%s.socket", alias);
+    g_autofree char *pidfile = g_build_filename(statedir, pidname, NULL);
+    g_autofree char *socketfile = g_build_filename(statedir, socketname, NULL);
+    qemuNbdkitProcess *proc;
+
+    if (srcPriv->nbdkitProcess)
+        return false;
+
+    switch (source->protocol) {
+        case VIR_STORAGE_NET_PROTOCOL_HTTP:
+        case VIR_STORAGE_NET_PROTOCOL_HTTPS:
+        case VIR_STORAGE_NET_PROTOCOL_FTP:
+        case VIR_STORAGE_NET_PROTOCOL_FTPS:
+        case VIR_STORAGE_NET_PROTOCOL_TFTP:
+            if (!virBitmapIsBitSet(caps->flags, QEMU_NBDKIT_CAPS_PLUGIN_CURL))
+                return false;
+            break;
+        case VIR_STORAGE_NET_PROTOCOL_SSH:
+            if (!virBitmapIsBitSet(caps->flags, QEMU_NBDKIT_CAPS_PLUGIN_SSH))
+                return false;
+            break;
+        case VIR_STORAGE_NET_PROTOCOL_NONE:
+        case VIR_STORAGE_NET_PROTOCOL_NBD:
+        case VIR_STORAGE_NET_PROTOCOL_RBD:
+        case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
+        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+        case VIR_STORAGE_NET_PROTOCOL_ISCSI:
+        case VIR_STORAGE_NET_PROTOCOL_VXHS:
+        case VIR_STORAGE_NET_PROTOCOL_NFS:
+        case VIR_STORAGE_NET_PROTOCOL_LAST:
+            return false;
+    }
+
+    proc = qemuNbdkitProcessNew(source, pidfile, socketfile);
+    proc->caps = g_object_ref(caps);
+    proc->user = user;
+    proc->group = group;
+
+    srcPriv->nbdkitProcess = proc;
+
+    return true;
+}
+
+
+void
+qemuNbdkitProcessFree(qemuNbdkitProcess *proc)
+{
+    g_clear_pointer(&proc->pidfile, g_free);
+    g_clear_pointer(&proc->socketfile, g_free);
+    g_clear_object(&proc->caps);
+    g_free(proc);
+}
diff --git a/src/qemu/qemu_nbdkit.h b/src/qemu/qemu_nbdkit.h
index 4aba7c8455..8844bba13c 100644
--- a/src/qemu/qemu_nbdkit.h
+++ b/src/qemu/qemu_nbdkit.h
@@ -20,10 +20,12 @@
 #pragma once
 
 #include "internal.h"
+#include "storage_source_conf.h"
 #include "virenum.h"
 #include "virfilecache.h"
 
 typedef struct _qemuNbdkitCaps qemuNbdkitCaps;
+typedef struct _qemuNbdkitProcess qemuNbdkitProcess;
 
 typedef enum {
     /* 0 */
@@ -42,6 +44,14 @@ qemuNbdkitCapsNew(const char *path);
 virFileCache *
 qemuNbdkitCapsCacheNew(const char *cachedir);
 
+bool
+qemuNbdkitInitStorageSource(qemuNbdkitCaps *nbdkitCaps,
+                            virStorageSource *source,
+                            char *statedir,
+                            const char *alias,
+                            uid_t user,
+                            gid_t group);
+
 bool
 qemuNbdkitCapsGet(qemuNbdkitCaps *nbdkitCaps,
                   qemuNbdkitCapsFlags flag);
@@ -52,3 +62,19 @@ qemuNbdkitCapsSet(qemuNbdkitCaps *nbdkitCaps,
 
 #define QEMU_TYPE_NBDKIT_CAPS qemu_nbdkit_caps_get_type()
 G_DECLARE_FINAL_TYPE(qemuNbdkitCaps, qemu_nbdkit_caps, QEMU, NBDKIT_CAPS, GObject);
+
+struct _qemuNbdkitProcess {
+    qemuNbdkitCaps *caps;
+    virStorageSource *source;
+
+    char *pidfile;
+    char *socketfile;
+    uid_t user;
+    gid_t group;
+    pid_t pid;
+};
+
+void
+qemuNbdkitProcessFree(qemuNbdkitProcess *proc);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuNbdkitProcess, qemuNbdkitProcessFree);
-- 
2.39.0



More information about the libvir-list mailing list