]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu_fd: Don't rely on fdset id allocation by qemu
authorPeter Krempa <pkrempa@redhat.com>
Thu, 5 May 2022 14:34:52 +0000 (16:34 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 16 May 2022 07:15:45 +0000 (09:15 +0200)
If we use our own fdset ID when hot-adding a fdset we can vastly
simplify our internals.

As a stop-gap when a fdset would be added behind libvirt's back we'll
validated that the fdset to be added is not yet used.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_fd.c
src/qemu/qemu_fd.h
tests/qemuhotplugtest.c
tests/qemumonitorjsontest.c

index 84e9d2bfdfc69f18ed00d60c3b1f723c6042103a..88039e8596e14c000a6a567d7e241b5e6b916780 100644 (file)
@@ -111,8 +111,12 @@ qemuFDPassNew(const char *prefix,
     fdpass->prefix = g_strdup(prefix);
     fdpass->useFDSet = true;
 
-    if (priv)
+    if (priv) {
         fdpass->fdSetID = qemuDomainFDSetIDNew(priv);
+        fdpass->path = g_strdup_printf("/dev/fdset/%u", fdpass->fdSetID);
+    } else {
+        fdpass->path = g_strdup_printf("/dev/fdset/monitor-fake");
+    }
 
     return fdpass;
 }
@@ -171,6 +175,11 @@ qemuFDPassAddFD(qemuFDPass *fdpass,
 
     newfd.opaque = g_strdup_printf("%s%s", fdpass->prefix, NULLSTR_EMPTY(suffix));
 
+    if (!fdpass->useFDSet) {
+        g_free(fdpass->path);
+        fdpass->path = g_strdup(newfd.opaque);
+    }
+
     VIR_APPEND_ELEMENT(fdpass->fds, fdpass->nfds, newfd);
 }
 
@@ -207,10 +216,10 @@ qemuFDPassTransferCommand(qemuFDPass *fdpass,
                                   fdpass->fds[i].opaque);
 
             virCommandAddArgList(cmd, "-add-fd", arg, NULL);
-
-            fdpass->path = g_strdup_printf("/dev/fdset/%u", fdpass->fdSetID);
         } else {
-            fdpass->path = g_strdup_printf("%u", fdpass->fds[i].fd);
+            /* for monitor use the older FD passing needs the FD number */
+            g_free(fdpass->path);
+            fdpass->path = g_strdup_printf("%d", fdpass->fds[i].fd);
         }
 
         fdpass->fds[i].fd = -1;
@@ -232,7 +241,6 @@ int
 qemuFDPassTransferMonitor(qemuFDPass *fdpass,
                           qemuMonitor *mon)
 {
-    int fdsetid = -1;
     size_t i;
 
     if (!fdpass)
@@ -240,6 +248,21 @@ qemuFDPassTransferMonitor(qemuFDPass *fdpass,
 
     if (qemuFDPassValidate(fdpass) < 0)
         return -1;
+    if (fdpass->useFDSet) {
+        g_autoptr(qemuMonitorFdsets) fdsets = NULL;
+
+        if (qemuMonitorQueryFdsets(mon, &fdsets) < 0)
+            return -1;
+
+        for (i = 0; i < fdsets->nfdsets; i++) {
+            if (fdsets->fdsets[i].id == fdpass->fdSetID) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("fdset '%u' is already in use by qemu"),
+                               fdpass->fdSetID);
+                return -1;
+            }
+        }
+    }
 
     for (i = 0; i < fdpass->nfds; i++) {
         if (fdpass->useFDSet) {
@@ -247,22 +270,15 @@ qemuFDPassTransferMonitor(qemuFDPass *fdpass,
 
             if (qemuMonitorAddFileHandleToSet(mon,
                                               fdpass->fds[i].fd,
-                                              fdsetid,
+                                              fdpass->fdSetID,
                                               fdpass->fds[i].opaque,
                                               &fdsetinfo) < 0)
                 return -1;
-
-            if (fdsetid == -1) {
-                fdpass->fdSetID = fdsetid = fdsetinfo.fdset;
-                fdpass->path = g_strdup_printf("/dev/fdset/%u", fdsetid);
-            }
         } else {
             if (qemuMonitorSendFileHandle(mon,
                                           fdpass->fds[i].opaque,
                                           fdpass->fds[i].fd) < 0)
                 return -1;
-
-            fdpass->path = g_strdup(fdpass->fds[i].opaque);
         }
 
         fdpass->passed = true;
@@ -272,33 +288,6 @@ qemuFDPassTransferMonitor(qemuFDPass *fdpass,
 }
 
 
-/**
- * qemuFDPassTransferMonitorFake:
- * @fdpass: The fd passing helper struct
- *
- * Simulate as if @fdpass was passed via monitor for callers which don't
- * actually wish to test that code path.
- */
-int
-qemuFDPassTransferMonitorFake(qemuFDPass *fdpass)
-{
-
-    if (!fdpass)
-        return 0;
-
-    if (qemuFDPassValidate(fdpass) < 0)
-        return -1;
-
-    if (fdpass->useFDSet) {
-        fdpass->path = g_strdup_printf("/dev/fdset/monitor-fake");
-    } else {
-        fdpass->path = g_strdup(fdpass->fds[0].opaque);
-    }
-
-    return 0;
-}
-
-
 /**
  * qemuFDPassTransferMonitorRollback:
  * @fdpass: The fd passing helper struct
index ef35daba8c14b9df98f9415fa3f893219aaa6c7e..d078d4ce5d7a6012127e5ba9b5abc776492e2627 100644 (file)
@@ -47,9 +47,6 @@ int
 qemuFDPassTransferMonitor(qemuFDPass *fdpass,
                           qemuMonitor *mon);
 
-int
-qemuFDPassTransferMonitorFake(qemuFDPass *fdpass);
-
 void
 qemuFDPassTransferMonitorRollback(qemuFDPass *fdpass,
                                   qemuMonitor *mon);
index 21302e0fce5df2319c40c29d3b708fc383ccdd75..fe8f0b58db91bbaad40815bbef00371a90a23407 100644 (file)
@@ -834,6 +834,7 @@ mymain(void)
                    "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK);
 
     DO_TEST_ATTACH("base-live", "interface-vdpa", false, true,
+                   "query-fdsets", "{\"return\":[{\"fdset-id\":99999}]}",
                    "add-fd", "{ \"return\": { \"fdset-id\": 1, \"fd\": 95 }}",
                    "netdev_add", QMP_OK, "device_add", QMP_OK);
     DO_TEST_DETACH("base-live", "interface-vdpa", false, false,
index e15c8533f6955fdac0a049afe45a69053fc0882d..c3ee771cbbc0a6b83bf0d033783857e500f00761 100644 (file)
@@ -725,7 +725,6 @@ qemuMonitorJSONTestAttachChardev(virDomainXMLOption *xmlopt,
 
     {
         g_autoptr(virDomainChrSourceDef) chr = virDomainChrSourceDefNew(xmlopt);
-        qemuDomainChrSourcePrivate *charpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(chr);
 
         chr->data.file.path = g_strdup("/test/path");
 
@@ -743,12 +742,6 @@ qemuMonitorJSONTestAttachChardev(virDomainXMLOption *xmlopt,
 
         chrdev.source = chr;
         ignore_value(testQemuPrepareHostBackendChardevOne(&dev, chr, NULL));
-        if (qemuFDPassTransferMonitorFake(charpriv->sourcefd) < 0)
-            ret = -1;
-
-        if (qemuFDPassTransferMonitorFake(charpriv->logfd) < 0)
-            ret = -1;
-
         CHECK("file", false,
               "{'id':'alias','backend':{'type':'file','data':{'out':'/dev/fdset/monitor-fake',"
                                                              "'append':true,"