43fe83
From 78e74acdcac9ada430b822afa6b5e1dadae575e8 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <78e74acdcac9ada430b822afa6b5e1dadae575e8.1378475168.git.jdenemar@redhat.com>
43fe83
From: Michal Privoznik <mprivozn@redhat.com>
43fe83
Date: Tue, 3 Sep 2013 15:18:46 +0200
43fe83
Subject: [PATCH] qemu: Handle huge number of queues correctly
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=651941
43fe83
43fe83
Currently, kernel supports up to 8 queues for a multiqueue tap device.
43fe83
However, if user tries to enter a huge number (e.g. one million) the tap
43fe83
allocation fails, as expected. But what is not expected is the log full
43fe83
of warnings:
43fe83
43fe83
    warning : virFileClose:83 : Tried to close invalid fd 0
43fe83
43fe83
The problem is, upon error we iterate over an array of FDs (handlers to
43fe83
queues) and VIR_FORCE_CLOSE() over each item. However, the array is
43fe83
pre-filled with zeros. Hence, we repeatedly close stdin. Ouch.
43fe83
But there's more. The queues allocation is done in virNetDevTapCreate()
43fe83
which cleans up the FDs in case of error. Then, its caller, the
43fe83
virNetDevTapCreateInBridgePort() iterates over the FD array and tries to
43fe83
close them too. And so does qemuNetworkIfaceConnect() and
43fe83
qemuBuildInterfaceCommandLine().
43fe83
(cherry picked from commit 1dc5dea7d605d3b02c64940fc3566a7765dce3c3)
43fe83
---
43fe83
 src/qemu/qemu_command.c | 10 +++++++---
43fe83
 src/util/virnetdevtap.c |  5 +++--
43fe83
 2 files changed, 10 insertions(+), 5 deletions(-)
43fe83
43fe83
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
43fe83
index 6dfd141..6e9657f 100644
43fe83
--- a/src/qemu/qemu_command.c
43fe83
+++ b/src/qemu/qemu_command.c
43fe83
@@ -405,7 +405,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
43fe83
 cleanup:
43fe83
     if (ret < 0) {
43fe83
         size_t i;
43fe83
-        for (i = 0; i < *tapfdSize; i++)
43fe83
+        for (i = 0; i < *tapfdSize && tapfd[i] >= 0; i++)
43fe83
             VIR_FORCE_CLOSE(tapfd[i]);
43fe83
         if (template_ifname)
43fe83
             VIR_FREE(net->ifname);
43fe83
@@ -7215,6 +7215,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
43fe83
             VIR_ALLOC_N(tapfdName, tapfdSize) < 0)
43fe83
             goto cleanup;
43fe83
 
43fe83
+        memset(tapfd, -1, tapfdSize * sizeof(tapfd[0]));
43fe83
+
43fe83
         if (qemuNetworkIfaceConnect(def, conn, driver, net,
43fe83
                                     qemuCaps, tapfd, &tapfdSize) < 0)
43fe83
             goto cleanup;
43fe83
@@ -7242,6 +7244,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
43fe83
             VIR_ALLOC_N(vhostfdName, vhostfdSize))
43fe83
             goto cleanup;
43fe83
 
43fe83
+        memset(vhostfd, -1, vhostfdSize * sizeof(vhostfd[0]));
43fe83
+
43fe83
         if (qemuOpenVhostNet(def, net, qemuCaps, vhostfd, &vhostfdSize) < 0)
43fe83
             goto cleanup;
43fe83
     }
43fe83
@@ -7303,13 +7307,13 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
43fe83
 cleanup:
43fe83
     if (ret < 0)
43fe83
         virDomainConfNWFilterTeardown(net);
43fe83
-    for (i = 0; tapfd && i < tapfdSize; i++) {
43fe83
+    for (i = 0; tapfd && i < tapfdSize && tapfd[i] >= 0; i++) {
43fe83
         if (ret < 0)
43fe83
             VIR_FORCE_CLOSE(tapfd[i]);
43fe83
         if (tapfdName)
43fe83
             VIR_FREE(tapfdName[i]);
43fe83
     }
43fe83
-    for (i = 0; vhostfd && i < vhostfdSize; i++) {
43fe83
+    for (i = 0; vhostfd && i < vhostfdSize && vhostfd[i] >= 0; i++) {
43fe83
         if (ret < 0)
43fe83
             VIR_FORCE_CLOSE(vhostfd[i]);
43fe83
         if (vhostfdName)
43fe83
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
43fe83
index 42e8dfe..fb173e3 100644
43fe83
--- a/src/util/virnetdevtap.c
43fe83
+++ b/src/util/virnetdevtap.c
43fe83
@@ -445,6 +445,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
43fe83
 {
43fe83
     virMacAddr tapmac;
43fe83
     char macaddrstr[VIR_MAC_STRING_BUFLEN];
43fe83
+    size_t i;
43fe83
 
43fe83
     if (virNetDevTapCreate(ifname, tapfd, tapfdSize, flags) < 0)
43fe83
         return -1;
43fe83
@@ -498,8 +499,8 @@ int virNetDevTapCreateInBridgePort(const char *brname,
43fe83
     return 0;
43fe83
 
43fe83
 error:
43fe83
-    while (tapfdSize)
43fe83
-        VIR_FORCE_CLOSE(tapfd[--tapfdSize]);
43fe83
+    for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
43fe83
+        VIR_FORCE_CLOSE(tapfd[i]);
43fe83
 
43fe83
     return -1;
43fe83
 }
43fe83
-- 
43fe83
1.8.3.2
43fe83