]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: block: Add support for passing FDs of disk images
authorPeter Krempa <pkrempa@redhat.com>
Mon, 2 May 2022 16:42:40 +0000 (18:42 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 9 Jan 2023 13:59:43 +0000 (14:59 +0100)
Prepare the internal data for passing FDs instead of having qemu open
the file internally.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
src/qemu/qemu_block.c
src/qemu/qemu_command.c

index 9bfb06ac08424900528048ef28d0babb91df8b8a..e865aa17f9e191cc0ef14d3e223fa546f6fc39f7 100644 (file)
@@ -673,22 +673,47 @@ qemuBlockStorageSourceGetSshProps(virStorageSource *src)
 
 static virJSONValue *
 qemuBlockStorageSourceGetFileProps(virStorageSource *src,
-                                   bool onlytarget)
+                                   bool onlytarget,
+                                   virTristateBool *autoReadOnly,
+                                   virTristateBool *readOnly)
 {
+    const char *path = src->path;
     const char *iomode = NULL;
     const char *prManagerAlias = NULL;
     virJSONValue *ret = NULL;
 
     if (!onlytarget) {
+        qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+
         if (src->pr)
             prManagerAlias = src->pr->mgralias;
 
         if (src->iomode != VIR_DOMAIN_DISK_IO_DEFAULT)
             iomode = virDomainDiskIoTypeToString(src->iomode);
+
+        if (srcpriv && srcpriv->fdpass) {
+            path = qemuFDPassGetPath(srcpriv->fdpass);
+
+            /* when passing a FD to qemu via the /dev/fdset mechanism qemu
+             * fetches the appropriate FD from the fdset by checking that it has
+             * the correct accessmode. Now with 'auto-read-only' in effect qemu
+             * wants to use a read-only FD first. If the user didn't pass multiple
+             * FDs the feature will not work regardless, so we'll disable it. */
+            if (src->fdtuple->nfds == 1) {
+                *autoReadOnly = VIR_TRISTATE_BOOL_ABSENT;
+
+                /* now we setup the normal readonly flag. If user requested write
+                 * access honour it */
+                if (src->fdtuple->writable)
+                    *readOnly = VIR_TRISTATE_BOOL_NO;
+                else
+                    *readOnly = virTristateBoolFromBool(src->readonly);
+            }
+        }
     }
 
     ignore_value(virJSONValueObjectAdd(&ret,
-                                       "s:filename", src->path,
+                                       "s:filename", path,
                                        "S:aio", iomode,
                                        "S:pr-manager", prManagerAlias,
                                        NULL) < 0);
@@ -818,7 +843,7 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource *src,
             driver = "file";
         }
 
-        if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget)))
+        if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget, &aro, &ro)))
             return NULL;
         break;
 
index 1f886580856e38af98d7fc09543247f24ed07741..9c05750d6620fc2e6ce9e3a95486a677d7ad0afd 100644 (file)
@@ -2146,6 +2146,25 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommand *cmd,
 }
 
 
+static int
+qemuBuildDiskSourceCommandLineFDs(virCommand *cmd,
+                                  virDomainDiskDef *disk)
+{
+    virStorageSource *n;
+
+    for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) {
+        qemuDomainStorageSourcePrivate *srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(n);
+
+        if (!srcpriv || !srcpriv->fdpass)
+            continue;
+
+        qemuFDPassTransferCommand(srcpriv->fdpass, cmd);
+    }
+
+    return 0;
+}
+
+
 static int
 qemuBuildDiskSourceCommandLine(virCommand *cmd,
                                virDomainDiskDef *disk,
@@ -2163,6 +2182,9 @@ qemuBuildDiskSourceCommandLine(virCommand *cmd,
         if (virStorageSourceIsEmpty(disk->src))
             return 0;
 
+        if (qemuBuildDiskSourceCommandLineFDs(cmd, disk) < 0)
+            return -1;
+
         if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->src)))
             return -1;