]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Move opening of vhost file descriptors for net devices into qemuBuildInterfaceC...
authorPeter Krempa <pkrempa@redhat.com>
Mon, 9 May 2022 15:42:08 +0000 (17:42 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 16 May 2022 07:15:46 +0000 (09:15 +0200)
Use the new infrastructure which stores the fds inside 'qemuFDPass'
objects in the private data.

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_command.c
src/qemu/qemu_hotplug.c
src/qemu/qemu_interface.c
src/qemu/qemu_interface.h
tests/qemuxml2argvmock.c

index 17b17404f9f960a36bea7b94fa73eb5d72532e20..0257d25143a1bf2c10c703b4ea6196bc2477df6e 100644 (file)
@@ -8693,23 +8693,27 @@ qemuInterfaceVhostuserConnect(virCommand *cmd,
 int
 qemuBuildInterfaceConnect(virDomainObj *vm,
                           virDomainNetDef *net,
-                          bool standalone G_GNUC_UNUSED)
+                          bool standalone)
 {
 
     qemuDomainObjPrivate *priv = vm->privateData;
     virDomainNetType actualType = virDomainNetGetActualType(net);
     qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
     VIR_AUTOCLOSE vdpafd = -1;
+    bool vhostfd = false;
 
     switch (actualType) {
     case VIR_DOMAIN_NET_TYPE_NETWORK:
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
+        vhostfd = true;
         break;
 
     case VIR_DOMAIN_NET_TYPE_DIRECT:
+        vhostfd = true;
         break;
 
     case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        vhostfd = true;
         break;
 
     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@@ -8734,6 +8738,11 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
         break;
     }
 
+    if (vhostfd && !standalone) {
+        if (qemuInterfaceOpenVhostNet(vm, net) < 0)
+            return -1;
+    }
+
     return 0;
 }
 
@@ -8930,26 +8939,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
         virNetDevSetMTU(net->ifname, net->mtu) < 0)
         goto cleanup;
 
-    if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
-         actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
-         actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
-         actualType == VIR_DOMAIN_NET_TYPE_DIRECT) &&
-        !standalone) {
-        /* Attempt to use vhost-net mode for these types of
-           network device */
-        vhostfdSize = net->driver.virtio.queues;
-        if (!vhostfdSize)
-            vhostfdSize = 1;
-
-        vhostfd = g_new0(int, vhostfdSize);
-        vhostfdName = g_new0(char *, vhostfdSize);
-
-        memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));
-
-        if (qemuInterfaceOpenVhostNet(def, net, vhostfd, &vhostfdSize) < 0)
-            goto cleanup;
-    }
-
     slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;
     if (slirp && !standalone) {
         int slirpfd = qemuSlirpGetFD(slirp);
index 90ca35bccfa96b719d6085cafab15f19a7e2a1a7..2bede03e35565de9871e5f582c4e99b69103b570 100644 (file)
@@ -1283,52 +1283,40 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
     switch (actualType) {
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
     case VIR_DOMAIN_NET_TYPE_NETWORK:
-        tapfdSize = vhostfdSize = net->driver.virtio.queues;
+        tapfdSize = net->driver.virtio.queues;
         if (!tapfdSize)
-            tapfdSize = vhostfdSize = 1;
+            tapfdSize = 1;
         tapfd = g_new0(int, tapfdSize);
         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
-        vhostfd = g_new0(int, vhostfdSize);
-        memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
         if (qemuInterfaceBridgeConnect(vm->def, driver, net,
                                        tapfd, &tapfdSize) < 0)
             goto cleanup;
         iface_connected = true;
-        if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
-            goto cleanup;
         break;
 
     case VIR_DOMAIN_NET_TYPE_DIRECT:
-        tapfdSize = vhostfdSize = net->driver.virtio.queues;
+        tapfdSize = net->driver.virtio.queues;
         if (!tapfdSize)
-            tapfdSize = vhostfdSize = 1;
+            tapfdSize = 1;
         tapfd = g_new0(int, tapfdSize);
         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
-        vhostfd = g_new0(int, vhostfdSize);
-        memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
         if (qemuInterfaceDirectConnect(vm->def, driver, net,
                                        tapfd, tapfdSize,
                                        VIR_NETDEV_VPORT_PROFILE_OP_CREATE) < 0)
             goto cleanup;
         iface_connected = true;
-        if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
-            goto cleanup;
         break;
 
     case VIR_DOMAIN_NET_TYPE_ETHERNET:
-        tapfdSize = vhostfdSize = net->driver.virtio.queues;
+        tapfdSize = net->driver.virtio.queues;
         if (!tapfdSize)
-            tapfdSize = vhostfdSize = 1;
+            tapfdSize = 1;
         tapfd = g_new0(int, tapfdSize);
         memset(tapfd, -1, sizeof(*tapfd) * tapfdSize);
-        vhostfd = g_new0(int, vhostfdSize);
-        memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize);
         if (qemuInterfaceEthernetConnect(vm->def, driver, net,
                                          tapfd, tapfdSize) < 0)
             goto cleanup;
         iface_connected = true;
-        if (qemuInterfaceOpenVhostNet(vm->def, net, vhostfd, &vhostfdSize) < 0)
-            goto cleanup;
         break;
 
     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@@ -1445,7 +1433,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
 
     if (!(netprops = qemuBuildHostNetProps(net,
                                            tapfdName, tapfdSize,
-                                           vhostfdName, vhostfdSize,
+                                           NULL, 0,
                                            slirpfdName)))
         goto cleanup;
 
@@ -1481,7 +1469,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
 
     if (qemuMonitorAddNetdev(priv->mon, &netprops,
                              tapfd, tapfdName, tapfdSize,
-                             vhostfd, vhostfdName, vhostfdSize,
+                             NULL, NULL, 0,
                              slirpfd, slirpfdName) < 0) {
         qemuDomainObjExitMonitor(vm);
         virDomainAuditNet(vm, NULL, net, "attach", false);
index e6a26e377f12db8eb340c517772973effb0009cf..c807be0745270df416708cca3d3cc933174bbd67 100644 (file)
@@ -688,49 +688,46 @@ qemuInterfacePrepareSlirp(virQEMUDriver *driver,
 
 /**
  * qemuInterfaceOpenVhostNet:
- * @def: domain definition
+ * @vm: domain object
  * @net: network definition
- * @qemuCaps: qemu binary capabilities
- * @vhostfd: array of opened vhost-net device
- * @vhostfdSize: number of file descriptors in @vhostfd array
  *
  * Open vhost-net, multiple times - if requested.
- * In case, no vhost-net is needed, @vhostfdSize is set to 0
- * and 0 is returned.
  *
  * Returns: 0 on success
  *         -1 on failure
  */
 int
-qemuInterfaceOpenVhostNet(virDomainDef *def,
-                          virDomainNetDef *net,
-                          int *vhostfd,
-                          size_t *vhostfdSize)
+qemuInterfaceOpenVhostNet(virDomainObj *vm,
+                          virDomainNetDef *net)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
     size_t i;
     const char *vhostnet_path = net->backend.vhost;
+    size_t vhostfdSize = net->driver.virtio.queues;
+    g_autofree char *prefix = g_strdup_printf("vhostfd-%s", net->info.alias);
+
+    if (!vhostfdSize)
+        vhostfdSize = 1;
 
     if (!vhostnet_path)
         vhostnet_path = "/dev/vhost-net";
 
     /* If running a plain QEMU guest, or
      * if the config says explicitly to not use vhost, return now */
-    if (def->virtType != VIR_DOMAIN_VIRT_KVM ||
-        net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) {
-        *vhostfdSize = 0;
+    if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM ||
+        net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU)
         return 0;
-    }
 
     /* If qemu doesn't support vhost-net mode (including the -netdev and
      * -device command options), don't try to open the device.
      */
-    if (!qemuDomainSupportsNicdev(def, net)) {
+    if (!qemuDomainSupportsNicdev(vm->def, net)) {
         if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("vhost-net is not supported with this QEMU binary"));
             return -1;
         }
-        *vhostfdSize = 0;
         return 0;
     }
 
@@ -741,35 +738,34 @@ qemuInterfaceOpenVhostNet(virDomainDef *def,
                            _("vhost-net is only supported for virtio network interfaces"));
             return -1;
         }
-        *vhostfdSize = 0;
         return 0;
     }
 
-    for (i = 0; i < *vhostfdSize; i++) {
-        vhostfd[i] = open(vhostnet_path, O_RDWR);
+    for (i = 0; i < vhostfdSize; i++) {
+        VIR_AUTOCLOSE fd = open(vhostnet_path, O_RDWR);
+        g_autoptr(qemuFDPass) pass = qemuFDPassNewDirect(prefix, priv);
+        g_autofree char *suffix = g_strdup_printf("%zu", i);
 
         /* If the config says explicitly to use vhost and we couldn't open it,
          * report an error.
          */
-        if (vhostfd[i] < 0) {
-            virDomainAuditNetDevice(def, net, vhostnet_path, false);
+        if (fd < 0) {
+            virDomainAuditNetDevice(vm->def, net, vhostnet_path, false);
             if (net->driver.virtio.name == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                _("vhost-net was requested for an interface, but is unavailable"));
-                goto error;
+                return -1;
             }
             VIR_WARN("Unable to open vhost-net. Opened so far %zu, requested %zu",
-                     i, *vhostfdSize);
-            *vhostfdSize = i;
+                     i, vhostfdSize);
             break;
         }
-    }
-    virDomainAuditNetDevice(def, net, vhostnet_path, *vhostfdSize);
-    return 0;
 
- error:
-    while (i--)
-        VIR_FORCE_CLOSE(vhostfd[i]);
+        qemuFDPassAddFD(pass, &fd, suffix);
+        netpriv->vhostfds = g_slist_prepend(netpriv->vhostfds, g_steal_pointer(&pass));
+    }
 
-    return -1;
+    netpriv->vhostfds = g_slist_reverse(netpriv->vhostfds);
+    virDomainAuditNetDevice(vm->def, net, vhostnet_path, vhostfdSize);
+    return 0;
 }
index 438d548065a8475fb99daef07d159a6c64d06ae7..a566d877b0e7f9a4ba5c2e597793514d5b17941b 100644 (file)
@@ -51,10 +51,8 @@ int qemuInterfaceBridgeConnect(virDomainDef *def,
                                size_t *tapfdSize)
     ATTRIBUTE_NONNULL(2);
 
-int qemuInterfaceOpenVhostNet(virDomainDef *def,
-                              virDomainNetDef *net,
-                              int *vhostfd,
-                              size_t *vhostfdSize) G_GNUC_NO_INLINE;
+int qemuInterfaceOpenVhostNet(virDomainObj *def,
+                              virDomainNetDef *net) G_GNUC_NO_INLINE;
 
 int qemuInterfacePrepareSlirp(virQEMUDriver *driver,
                               virDomainNetDef *net,
index 08f176667daa254ec6e8635c5add3816d9aa957b..aa82ffa2d673b4427b78e4a7b1804f9b1fa18390 100644 (file)
@@ -226,20 +226,32 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path G_GNUC_UNUSED,
 }
 
 int
-qemuInterfaceOpenVhostNet(virDomainDef *def G_GNUC_UNUSED,
-                          virDomainNetDef *net,
-                          int *vhostfd,
-                          size_t *vhostfdSize)
+qemuInterfaceOpenVhostNet(virDomainObj *vm,
+                          virDomainNetDef *net)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
+    g_autofree char *prefix = g_strdup_printf("vhostfd-%s", net->info.alias);
+    size_t vhostfdSize = net->driver.virtio.queues;
     size_t i;
 
-    if (!virDomainNetIsVirtioModel(net)) {
-        *vhostfdSize = 0;
+    if (!vhostfdSize)
+         vhostfdSize = 1;
+
+    if (!virDomainNetIsVirtioModel(net))
         return 0;
+
+    for (i = 0; i < vhostfdSize; i++) {
+        g_autoptr(qemuFDPass) pass = qemuFDPassNewDirect(prefix, priv);
+        g_autofree char *suffix = g_strdup_printf("%zu", i);
+        int fd = STDERR_FILENO + 42 + i;
+
+        qemuFDPassAddFD(pass, &fd, suffix);
+        netpriv->vhostfds = g_slist_prepend(netpriv->vhostfds, g_steal_pointer(&pass));
     }
 
-    for (i = 0; i < *vhostfdSize; i++)
-        vhostfd[i] = STDERR_FILENO + 42 + i;
+    netpriv->vhostfds = g_slist_reverse(netpriv->vhostfds);
+
     return 0;
 }