[PATCH 21/37] qemu: Move opening of vhost file descriptors for net devices into qemuBuildInterfaceConnect

Peter Krempa pkrempa at redhat.com
Tue May 10 15:19:57 UTC 2022


Use the new infrastructure which stores the fds inside 'qemuFDPass'
objects in the private data.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_command.c   | 31 +++++++--------------
 src/qemu/qemu_hotplug.c   | 28 ++++++-------------
 src/qemu/qemu_interface.c | 58 ++++++++++++++++++---------------------
 src/qemu/qemu_interface.h |  6 ++--
 tests/qemuxml2argvmock.c  | 28 +++++++++++++------
 5 files changed, 67 insertions(+), 84 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 78ea638c26..0b527784c5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8671,23 +8671,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:
@@ -8712,6 +8716,11 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
         break;
     }

+    if (vhostfd && !standalone) {
+        if (qemuInterfaceOpenVhostNet(vm, net) < 0)
+            return -1;
+    }
+
     return 0;
 }

@@ -8908,26 +8917,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);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 90ca35bccf..2bede03e35 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -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);
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index e6a26e377f..c807be0745 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -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;
 }
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
index 438d548065..a566d877b0 100644
--- a/src/qemu/qemu_interface.h
+++ b/src/qemu/qemu_interface.h
@@ -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,
diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c
index 08f176667d..aa82ffa2d6 100644
--- a/tests/qemuxml2argvmock.c
+++ b/tests/qemuxml2argvmock.c
@@ -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;
 }

-- 
2.35.1



More information about the libvir-list mailing list