|
|
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 |
|