]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Prepare data for FD-passed disk image sources
authorPeter Krempa <pkrempa@redhat.com>
Wed, 4 May 2022 13:00:18 +0000 (15:00 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 9 Jan 2023 13:59:43 +0000 (14:59 +0100)
When starting up a VM with FD-passed images we need to look up the
corresponding named FD set and associate it with the virStorageSource
based on the name.

The association is brought into virStorageSource as security labelling
code will need to access the FD to perform selinux labelling.

Similarly when startup is complete in certain cases we no longer need to
keep the copy of FDs and thus can close them.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
src/conf/storage_source_conf.c
src/conf/storage_source_conf.h
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_hotplug.c

index 8b67e511e2d6377b88e58d27bde74f07ec555eb5..1c11eacb9dbfecfd18f73ca392b47f1783e50d02 100644 (file)
@@ -886,6 +886,9 @@ virStorageSourceCopy(const virStorageSource *src,
             return NULL;
     }
 
+    if (src->fdtuple)
+        def->fdtuple = g_object_ref(src->fdtuple);
+
     /* ssh config passthrough for libguestfs */
     def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled;
     def->ssh_user = g_strdup(src->ssh_user);
@@ -1170,6 +1173,8 @@ virStorageSourceClear(virStorageSource *def)
 
     virStorageSourceInitiatorClear(&def->initiator);
 
+    g_clear_pointer(&def->fdtuple, g_object_unref);
+
     /* clear everything except the class header as the object APIs
      * will break otherwise */
     memset((char *) def + sizeof(def->parent), 0,
index 9c07eef200d868988ae20f740a3d07de5eb98805..f981261ff462e025abbd00c27bf99b90d37db2ad 100644 (file)
@@ -415,6 +415,8 @@ struct _virStorageSource {
      * registered with a full index (vda[3]) so that we can properly report just
      * one event for it */
     bool thresholdEventWithIndex;
+
+    virStorageSourceFDTuple *fdtuple;
 };
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSource, virObjectUnref);
index e6cbd4c0cb7599e9d503101cd2caec2971854049..9fd3c39646f59e27f25c6784f4e8d141025c145b 100644 (file)
@@ -874,6 +874,7 @@ qemuDomainStorageSourcePrivateDispose(void *obj)
     g_clear_pointer(&priv->encinfo, qemuDomainSecretInfoFree);
     g_clear_pointer(&priv->httpcookie, qemuDomainSecretInfoFree);
     g_clear_pointer(&priv->tlsKeySecret, qemuDomainSecretInfoFree);
+    g_clear_pointer(&priv->fdpass, qemuFDPassFree);
 }
 
 
@@ -10824,6 +10825,61 @@ qemuDomainPrepareDiskSourceLegacy(virDomainDiskDef *disk,
 }
 
 
+static int
+qemuDomainPrepareStorageSourceFDs(virStorageSource *src,
+                                  qemuDomainObjPrivate *priv)
+{
+    qemuDomainStorageSourcePrivate *srcpriv = NULL;
+    virStorageType actualType = virStorageSourceGetActualType(src);
+    virStorageSourceFDTuple *fdt = NULL;
+    size_t i;
+
+    if (actualType != VIR_STORAGE_TYPE_FILE &&
+        actualType != VIR_STORAGE_TYPE_BLOCK)
+        return 0;
+
+    if (!virStorageSourceIsFD(src))
+        return 0;
+
+    if (!(fdt = virHashLookup(priv->fds, src->fdgroup))) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("file descriptor group '%s' was not associated with the domain"),
+                       src->fdgroup);
+        return -1;
+    }
+
+    srcpriv = qemuDomainStorageSourcePrivateFetch(src);
+
+    srcpriv->fdpass = qemuFDPassNew(src->nodestorage, priv);
+
+    for (i = 0; i < fdt->nfds; i++) {
+        g_autofree char *idx = g_strdup_printf("%zu", i);
+        int tmpfd;
+
+        if (fdt->testfds) {
+            /* when testing we want to use stable FD numbers provided by the test
+             * case */
+            tmpfd = dup2(fdt->fds[i], fdt->testfds[i]);
+        } else {
+            tmpfd = dup(fdt->fds[i]);
+        }
+
+        if (tmpfd < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("failed to duplicate file descriptor for fd group '%s'"),
+                           src->fdgroup);
+            return -1;
+        }
+
+        qemuFDPassAddFD(srcpriv->fdpass, &tmpfd, idx);
+    }
+
+    src->fdtuple = g_object_ref(fdt);
+
+    return 0;
+}
+
+
 int
 qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
                                                virStorageSource *src,
@@ -10861,6 +10917,9 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
     if (qemuDomainPrepareStorageSourceNFS(src) < 0)
         return -1;
 
+    if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0)
+        return -1;
+
     return 0;
 }
 
@@ -12213,6 +12272,28 @@ qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv)
 }
 
 
+/**
+ * qemuDomainCleanupStorageSourceFD:
+ * @src: start of the chain to clear
+ *
+ * Cleans up the backing chain starting at @src of FD tuple structures for
+ * all FD-tuples which didn't request explicit relabelling and thus the struct
+ * is no longer needed.
+ */
+void
+qemuDomainCleanupStorageSourceFD(virStorageSource *src)
+{
+    virStorageSource *n;
+
+    for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
+        if (virStorageSourceIsFD(n) && n->fdtuple) {
+            if (!n->fdtuple->tryRestoreLabel)
+                g_clear_pointer(&n->fdtuple, g_object_unref);
+        }
+    }
+}
+
+
 /**
  * qemuDomainStartupCleanup:
  *
@@ -12222,5 +12303,10 @@ qemuDomainSchedCoreStop(qemuDomainObjPrivate *priv)
 void
 qemuDomainStartupCleanup(virDomainObj *vm)
 {
+    size_t i;
+
     qemuDomainSecretDestroy(vm);
+
+    for (i = 0; i < vm->def->ndisks; i++)
+        qemuDomainCleanupStorageSourceFD(vm->def->disks[i]->src);
 }
index 11ef3e7b64f4afb0765c5ac9d4ddf2c83c54957f..5114a311fb21eb8fdb5667c29bd67be614d75a35 100644 (file)
@@ -305,6 +305,9 @@ struct _qemuDomainStorageSourcePrivate {
 
     /* key for decrypting TLS certificate */
     qemuDomainSecretInfo *tlsKeySecret;
+
+    /* file descriptors if user asks for FDs to be passed */
+    qemuFDPass *fdpass;
 };
 
 virObject *qemuDomainStorageSourcePrivateNew(void);
@@ -925,6 +928,8 @@ int qemuDomainSecretChardevPrepare(virQEMUDriverConfig *cfg,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(4);
 
+void qemuDomainCleanupStorageSourceFD(virStorageSource *src);
+
 void qemuDomainStartupCleanup(virDomainObj *vm);
 
 int qemuDomainSecretPrepare(virQEMUDriver *driver,
index 6e300f547cf3ac2c899f42e292cb2925a4c268b5..dba699a8a8d8fc3ac128ba6a5b8e087ccfa57353 100644 (file)
@@ -1016,6 +1016,7 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *driver,
             ignore_value(qemuHotplugRemoveManagedPR(vm, VIR_ASYNC_JOB_NONE));
     }
     qemuDomainSecretDiskDestroy(disk);
+    qemuDomainCleanupStorageSourceFD(disk->src);
 
     return ret;
 }