[libvirt] [BUG] libvirtd on destination crash frequently while migrating vms concurrently
by Wangyufei (A)
Hello,
I found a problem that libvirtd on destination crash frequently while migrating vms concurrently. For example, if I migrate 10 vms concurrently ceaselessly, then after about 30 minutes the libvirtd on destination will crash. So I analyzed and found two bugs during migration process.
First, during migration prepare phase on destination, libvirtd assigns ports to qemu to be startd on destination. But the port increase operation is not aomic, so there's a chance that multi vms get the same port, and only the first one can start successfully, others will fail to start. I've applied a patch to solve this bug, and I test it, it works well. If only this bug exists, libvirtd will not crash. The second bug is fatal.
Second, I found the libvirtd crash because of segment fault which is produced by accessing vm released. Apparently it's caused by multi-thread operation, thread A access vm data which has released by thread B. At last I proved my thought right.
Step 1. Because of bug one, the port is already occupied, so qemu on destination failed to start and sent a HANGUP signal to libvirtd, then libvirtd received this VIR_EVENT_HANDLE_HANGUP event, thread A dealing with events called qemuProcessHandleMonitorEOF as following:
#0 qemuProcessHandleMonitorEOF (mon=0x7f4dcd9c3130, vm=0x7f4dcd9c9780)
at qemu/qemu_process.c:399
#1 0x00007f4dc18d9e87 in qemuMonitorIO (watch=68, fd=27, events=8,
opaque=0x7f4dcd9c3130) at qemu/qemu_monitor.c:668
#2 0x00007f4dccae6604 in virEventPollDispatchHandles (nfds=18,
fds=0x7f4db4017e70) at util/vireventpoll.c:500
#3 0x00007f4dccae7ff2 in virEventPollRunOnce () at util/vireventpoll.c:646
#4 0x00007f4dccae60e4 in virEventRunDefaultImpl () at util/virevent.c:273
#5 0x00007f4dccc40b25 in virNetServerRun (srv=0x7f4dcd8d26b0)
at rpc/virnetserver.c:1106
#6 0x00007f4dcd6164c9 in main (argc=3, argv=0x7fff8d8f9f88)
at libvirtd.c:1518
static int virEventPollDispatchHandles(int nfds, struct pollfd *fds) {
......
/*
deleted flag is still false now, so we pass through to qemuProcessHandleMonitorEOF
*/
if (eventLoop.handles[i].deleted) {
EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
eventLoop.handles[i].watch, eventLoop.handles[i].fd);
continue;
}
Step 2: Thread B dealing with migration on destination set deleted flag in virEventPollRemoveHandle as following:
#0 virEventPollRemoveHandle (watch=74) at util/vireventpoll.c:176
#1 0x00007f4dccae5e6f in virEventRemoveHandle (watch=74)
at util/virevent.c:97
#2 0x00007f4dc18d8ca8 in qemuMonitorClose (mon=0x7f4dbc030910)
at qemu/qemu_monitor.c:831
#3 0x00007f4dc18bec63 in qemuProcessStop (driver=0x7f4dcd9bd400,
vm=0x7f4dbc00ed20, reason=VIR_DOMAIN_SHUTOFF_FAILED, flags=0)
at qemu/qemu_process.c:4302
#4 0x00007f4dc18c1a83 in qemuProcessStart (conn=0x7f4dbc031020,
driver=0x7f4dcd9bd400, vm=0x7f4dbc00ed20,
migrateFrom=0x7f4dbc01af90 "tcp:[::]:49152", stdin_fd=-1,
stdin_path=0x0, snapshot=0x0,
vmop=VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START, flags=6)
at qemu/qemu_process.c:4145
#5 0x00007f4dc18cc688 in qemuMigrationPrepareAny (driver=0x7f4dcd9bd400,
Step 3: Thread B cleanup vm in qemuMigrationPrepareAny after qemuProcessStart failed.
#0 virDomainObjDispose (obj=0x7f4dcd9c9780) at conf/domain_conf.c:2009
#1 0x00007f4dccb0ccd9 in virObjectUnref (anyobj=0x7f4dcd9c9780)
at util/virobject.c:266
#2 0x00007f4dccb42340 in virDomainObjListRemove (doms=0x7f4dcd9bd4f0,
dom=0x7f4dcd9c9780) at conf/domain_conf.c:2342
#3 0x00007f4dc189ac33 in qemuDomainRemoveInactive (driver=0x7f4dcd9bd400,
vm=0x7f4dcd9c9780) at qemu/qemu_domain.c:1993
#4 0x00007f4dc18ccad5 in qemuMigrationPrepareAny (driver=0x7f4dcd9bd400,
Step 4: Thread A access priv which is released by thread B before, then libvirtd crash, bomb!
static void
qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm)
{
virQEMUDriverPtr driver = qemu_driver;
virDomainEventPtr event = NULL;
qemuDomainObjPrivatePtr priv;
int eventReason = VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN;
int stopReason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
const char *auditReason = "shutdown";
VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name);
virObjectLock(vm);
priv = vm->privateData;
(gdb) p priv
$1 = (qemuDomainObjPrivatePtr) 0x0
if (priv->beingDestroyed) {
At last if anything bad happened to make qemuProcessStart failed during migration on destination, we'll be in the big trouble that accessing some memory freed. I didn't find any locks or flags exist could stop this happening. Please help me out, thanks a lot.
Best Regards,
-WangYufei
11 years, 6 months
[libvirt] [PATCH 0/3] Fix scalability of LXC containers
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Since we switched to use systemd for creating cgroups we have a
scalability problem with LXC out of the box. Only ~230 containers
can be created before we hit the default dbus-daemon connection
limit. This series makes libvirt_lxc close its dbus connection
once the guest has started, avoiding the problem.
Daniel P. Berrange (3):
Allow use of a private dbus bus connection
Add a method for closing the dbus system bus connection
Make LXC controller use a private dbus connection & close it
src/Makefile.am | 1 +
src/libvirt_private.syms | 2 ++
src/lxc/lxc_controller.c | 9 +++++++++
src/util/virdbus.c | 28 +++++++++++++++++++++++++++-
src/util/virdbus.h | 3 +++
5 files changed, 42 insertions(+), 1 deletion(-)
--
1.8.3.1
11 years, 6 months
[libvirt] [PATCH] Fix flaw in detecting log format
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The log message regex has been
[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+[0-9]{4}: [0-9]+: debug|info|warning|error :
The precedence of '|' is high though, so this is equivalent to matching
[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+[0-9]{4}: [0-9]+: debug
Or
info
Or
warning
Or
error :
Which is clearly not what it should have done. This caused the code to
skip over things which are not log messages. The solution is to simply
add brackets.
A test case is also added to validate correctness.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
.gitignore | 1 +
src/util/virlog.c | 5 +++-
tests/Makefile.am | 5 ++++
tests/virlogtest.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 77 insertions(+), 1 deletion(-)
create mode 100644 tests/virlogtest.c
diff --git a/.gitignore b/.gitignore
index b5824dc..db5abcd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -210,6 +210,7 @@
/tests/virkeycodetest
/tests/virkeyfiletest
/tests/virlockspacetest
+/tests/virlogtest
/tests/virnet*test
/tests/virportallocatortest
/tests/virshtest
diff --git a/src/util/virlog.c b/src/util/virlog.c
index 7ee5117..cc5032f 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -83,7 +83,7 @@ static regex_t *virLogRegex = NULL;
#define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}"
#define VIR_LOG_TIME_REGEX "[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}\\+[0-9]{4}"
#define VIR_LOG_PID_REGEX "[0-9]+"
-#define VIR_LOG_LEVEL_REGEX "debug|info|warning|error"
+#define VIR_LOG_LEVEL_REGEX "(debug|info|warning|error)"
#define VIR_LOG_REGEX \
VIR_LOG_DATE_REGEX " " VIR_LOG_TIME_REGEX ": " \
@@ -1623,6 +1623,9 @@ virLogSetFromEnv(void)
{
char *debugEnv;
+ if (virLogInitialize() < 0)
+ return;
+
debugEnv = getenv("LIBVIRT_DEBUG");
if (debugEnv && *debugEnv)
virLogParseDefaultPriority(debugEnv);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3eda522..250cd8c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -126,6 +126,7 @@ test_programs = virshtest sockettest \
viridentitytest \
virkeycodetest \
virlockspacetest \
+ virlogtest \
virstringtest \
virportallocatortest \
sysinfotest \
@@ -716,6 +717,10 @@ virlockspacetest_SOURCES = \
virlockspacetest.c testutils.h testutils.c
virlockspacetest_LDADD = $(LDADDS)
+virlogtest_SOURCES = \
+ virlogtest.c testutils.h testutils.c
+virlogtest_LDADD = $(LDADDS)
+
virportallocatortest_SOURCES = \
virportallocatortest.c testutils.h testutils.c
virportallocatortest_LDADD = $(LDADDS)
diff --git a/tests/virlogtest.c b/tests/virlogtest.c
new file mode 100644
index 0000000..dfe0f75
--- /dev/null
+++ b/tests/virlogtest.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "testutils.h"
+
+#include "virlog.h"
+
+struct testLogMatchData {
+ const char *str;
+ bool res;
+};
+
+static int
+testLogMatch(const void *opaque)
+{
+ const struct testLogMatchData *data = opaque;
+
+ bool got = virLogProbablyLogMessage(data->str);
+ if (got != data->res) {
+ fprintf(stderr, "Expected '%d' but got '%d' for '%s'\n",
+ data->res, got, data->str);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int
+mymain(void)
+{
+ int ret = 0;
+
+#define TEST_LOG_MATCH(str, res) \
+ do { \
+ struct testLogMatchData data = { \
+ str, res \
+ }; \
+ if (virtTestRun("testLogMatch " # str, testLogMatch, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
+ TEST_LOG_MATCH("2013-10-11 15:43:43.866+0000: 28302: info : libvirt version: 1.1.3", true);
+
+ TEST_LOG_MATCH("libvirt: error : cannot execute binary /usr/libexec/libvirt_lxc: No such file or directory", false);
+
+ return ret;
+}
+
+VIRT_TEST_MAIN(mymain)
--
1.8.3.1
11 years, 6 months
[libvirt] [PATCH] nwfilter: fix a typo in nwfilter_gentech_driver.c
by Hongwei Bi
s/occcurred/occurred
---
src/nwfilter/nwfilter_gentech_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index 5961165..16878a4 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -193,7 +193,7 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table,
* Create a hashmap used for evaluating the firewall rules. Initializes
* it with the standard variable 'MAC' and 'IP' if provided.
*
- * Returns pointer to hashmap, NULL if an error occcurred.
+ * Returns pointer to hashmap, NULL if an error occurred.
*/
virNWFilterHashTablePtr
virNWFilterCreateVarHashmap(char *macaddr,
--
1.8.1.2
11 years, 6 months
[libvirt] [PATCH] rpc: Fix getsockopt on Snow Leopard and lower
by Doug Goldstein
Since 5a468b38b6 we use SOL_LOCAL for the 2nd argument of getsockopt()
however Lion added the define SOL_LOCAL set to 0, which is the value to
the 2nd argument of getsockopt() for Unix sockets on Mac OS X. So
instead of using the define just pass 0 so we restore compatibility
with Snow Leopard and Leopard.
Reported at https://github.com/mxcl/homebrew/pull/23141
---
v2:
* Refactored ifdef outside of the function and create a define for the
second argument of getsockopt().
---
src/rpc/virnetsocket.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index a2823ef..e8cdfa6 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -1149,6 +1149,23 @@ cleanup:
}
#elif defined(LOCAL_PEERCRED)
+/* VIR_SOL_PEERCRED - the value needed to let getsockopt() work with
+ * LOCAL_PEERCRED
+ */
+# ifdef __APPLE__
+# ifdef SOL_LOCAL
+# define VIR_SOL_PEERCRED SOL_LOCAL
+# else
+/* Prior to Mac OS X 10.7, SOL_LOCAL was not defined and users were
+ * expected to supply 0 as the second value for getsockopt() when using
+ * LOCAL_PEERCRED
+ */
+# define VIR_SOL_PEERCRED 0
+# endif
+# else
+# define VIR_SOL_PEERCRED SOL_SOCKET
+# endif
+
int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
uid_t *uid,
gid_t *gid,
@@ -1159,11 +1176,7 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
socklen_t cr_len = sizeof(cr);
virObjectLock(sock);
-# if defined(__APPLE__)
- if (getsockopt(sock->fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
-# else
- if (getsockopt(sock->fd, SOL_SOCKET, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
-# endif
+ if (getsockopt(sock->fd, VIR_SOL_PEERCRED, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
virReportSystemError(errno, "%s",
_("Failed to get client socket identity"));
virObjectUnlock(sock);
--
1.8.1.5
11 years, 6 months
[libvirt] [PATCH] qemu: Include listenAddress in debug prints
by Michal Privoznik
After my patches, some functions gained one more argument
(@listenAddress) which wasn't included in debug printing of
arguments they were called with. Functions in question are:
qemuMigrationPrepareDirect and qemuMigrationPerform.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_migration.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 32121c6..38edadb 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2532,10 +2532,10 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
VIR_DEBUG("driver=%p, dconn=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, uri_in=%s, uri_out=%p, "
- "def=%p, origname=%s, flags=%lx",
+ "def=%p, origname=%s, listenAddress=%s, flags=%lx",
driver, dconn, NULLSTR(cookiein), cookieinlen,
cookieout, cookieoutlen, NULLSTR(uri_in), uri_out,
- *def, origname, flags);
+ *def, origname, NULLSTR(listenAddress), flags);
*uri_out = NULL;
@@ -4243,11 +4243,11 @@ qemuMigrationPerform(virQEMUDriverPtr driver,
bool v3proto)
{
VIR_DEBUG("driver=%p, conn=%p, vm=%p, xmlin=%s, dconnuri=%s, "
- "uri=%s, graphicsuri=%s, "
+ "uri=%s, graphicsuri=%s, listenAddress=%s"
"cookiein=%s, cookieinlen=%d, cookieout=%p, cookieoutlen=%p, "
"flags=%lx, dname=%s, resource=%lu, v3proto=%d",
driver, conn, vm, NULLSTR(xmlin), NULLSTR(dconnuri),
- NULLSTR(uri), NULLSTR(graphicsuri),
+ NULLSTR(uri), NULLSTR(graphicsuri), NULLSTR(listenAddress),
NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen,
flags, NULLSTR(dname), resource, v3proto);
--
1.8.1.5
11 years, 6 months
[libvirt] [PATCH] Fix: helper function virCompareLimitUlong should return -1 when the latter parameter is 0
by mars@linux.vnet.ibm.com
From: Bing Bu Cao <mars(a)linux.vnet.ibm.com>
The helper function virCompareLimitUlong compare limit values,
where value of 0 is equal to unlimited, if the latter parameter is 0,
it should return -1 instead of 1, hence the user can only set hard_limit when
swap_hard_limit currently is unlimited.
Signed-off-by: Bing Bu Cao <mars(a)linux.vnet.ibm.com>
---
src/util/virutil.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/util/virutil.c b/src/util/virutil.c
index d9e0bc4..3dcf1fe 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -2067,6 +2067,9 @@ virCompareLimitUlong(unsigned long long a, unsigned long b)
if (a == b)
return 0;
+ if (0 == b)
+ return -1;
+
if (a == 0 || a > b)
return 1;
--
1.7.7.6
11 years, 6 months
[libvirt] [PATCH 1/2] VMware: Simplify array walk for driver type
by Doug Goldstein
Rather than walking the possible driver backends by handle, use a helper
function. Additionally I've done a bit of refactoring in the code over
the past few commits so add myself to the copyright line.
---
src/vmware/vmware_driver.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
index 25adb15..79954e0 100644
--- a/src/vmware/vmware_driver.c
+++ b/src/vmware/vmware_driver.c
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2011-2012 Red Hat, Inc.
* Copyright 2010, diateam (www.diateam.net)
+ * Copyright (C) 2013. Doug Goldstein <cardoe(a)cardoe.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -156,13 +157,8 @@ vmwareConnectOpen(virConnectPtr conn,
goto cleanup;
}
- driver->type = -1;
- for (i = 0; i < VMWARE_DRIVER_LAST; i++) {
- if (STREQ(tmp, vmwareDriverTypeToString(i))) {
- driver->type = i;
- break;
- }
- }
+ /* Match the non-'vmware' part of the scheme as the driver backend */
+ driver->type = vmwareDriverTypeFromString(tmp);
if (driver->type == -1) {
virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to find valid "
--
1.8.1.5
11 years, 6 months
[libvirt] [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
by Wangyufei (A)
>From f56b290eab36bbb7a9ac53778a55638d473504d1 Mon Sep 17 00:00:00 2001
From: WangYufei <james.wangyufei(a)huawei.com>
Date: Fri, 11 Oct 2013 11:27:13 +0800
Subject: [PATCH] qemu_migrate: Fix assign the same port when migrating concurrently
When we migrate vms concurrently, there's a chance that libvirtd on destination assign the same port for different migrations, which will lead to migration failed during migration prepare phase on destination. So we use virPortAllocator here to solve the problem.
Signed-off-by: WangYufei <james.wangyufei(a)huawei.com>
---
src/qemu/qemu_command.h | 3 +++
src/qemu/qemu_conf.h | 6 +++---
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 6 ++++++
src/qemu/qemu_migration.c | 28 +++++++++++++++++++++-------
5 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 2e2acfb..3277ba4 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -51,6 +51,9 @@
# define QEMU_WEBSOCKET_PORT_MIN 5700
# define QEMU_WEBSOCKET_PORT_MAX 65535
+# define QEMU_MIGRATION_PORT_MIN 49152
+# define QEMU_MIGRATION_PORT_MAX 49215
+
typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
struct _qemuBuildCommandLineCallbacks {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index da29a2a..3176085 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -221,6 +221,9 @@ struct _virQEMUDriver {
/* Immutable pointer, self-locking APIs */
virPortAllocatorPtr webSocketPorts;
+ /* Immutable pointer, self-locking APIs */
+ virPortAllocatorPtr migrationPorts;
+
/* Immutable pointer, lockless APIs*/
virSysinfoDefPtr hostsysinfo;
@@ -242,9 +245,6 @@ struct _qemuDomainCmdlineDef {
char **env_value;
};
-/* Port numbers used for KVM migration. */
-# define QEMUD_MIGRATION_FIRST_PORT 49152
-# define QEMUD_MIGRATION_NUM_PORTS 64
void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 21f116c..16c55a6 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate {
unsigned long migMaxBandwidth;
char *origname;
int nbdPort; /* Port used for migration with NBD */
+ int migrationPort;
virChrdevsPtr devs;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index cfdbb9a..c08a73c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged,
cfg->webSocketPortMax)) == NULL)
goto error;
+ if ((qemu_driver->migrationPorts =
+ virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
+ QEMU_MIGRATION_PORT_MAX)) == NULL)
+ goto error;
+
if (qemuSecurityInit(qemu_driver) < 0)
goto error;
@@ -993,6 +998,7 @@ qemuStateCleanup(void) {
virObjectUnref(qemu_driver->domains);
virObjectUnref(qemu_driver->remotePorts);
virObjectUnref(qemu_driver->webSocketPorts);
+ virObjectUnref(qemu_driver->migrationPorts);
virObjectUnref(qemu_driver->xmlopt);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 3a1aab7..93ae237 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2147,6 +2147,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
qemuDomainJobTypeToString(priv->job.active),
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+ priv->migrationPort = 0;
+
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
return;
qemuDomainObjDiscardAsyncJob(driver, vm);
@@ -2297,6 +2300,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
*def = NULL;
priv = vm->privateData;
+ priv->migrationPort = port;
if (VIR_STRDUP(priv->origname, origname) < 0)
goto cleanup;
@@ -2415,6 +2419,11 @@ cleanup:
VIR_FREE(xmlout);
VIR_FORCE_CLOSE(dataFD[0]);
VIR_FORCE_CLOSE(dataFD[1]);
+ if (ret < 0) {
+ virPortAllocatorRelease(driver->migrationPorts, port);
+ if (priv)
+ priv->migrationPort = 0;
+ }
if (vm) {
if (ret >= 0 || vm->persistent)
virObjectUnlock(vm);
@@ -2493,7 +2502,6 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
const char *origname,
unsigned long flags)
{
- static int port = 0;
int this_port;
char *hostname = NULL;
const char *p;
@@ -2521,8 +2529,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
* to be a correct hostname which refers to the target machine).
*/
if (uri_in == NULL) {
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
- if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
+ if (virPortAllocatorAcquire(driver->migrationPorts,
+ (unsigned short *)&this_port) < 0)
+ goto cleanup;
/* Get hostname */
if ((hostname = virGetHostname()) == NULL)
@@ -2578,9 +2587,9 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
if (uri->port == 0) {
/* Generate a port */
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
- if (port == QEMUD_MIGRATION_NUM_PORTS)
- port = 0;
+ if (virPortAllocatorAcquire(driver->migrationPorts,
+ (unsigned short *)&this_port) < 0)
+ goto cleanup;
/* Caller frees */
if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0)
@@ -2600,8 +2609,11 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
cleanup:
virURIFree(uri);
VIR_FREE(hostname);
- if (ret != 0)
+ if (ret != 0) {
VIR_FREE(*uri_out);
+ virPortAllocatorRelease(driver->migrationPorts,
+ (unsigned short)this_port);
+ }
return ret;
}
@@ -4370,6 +4382,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
}
qemuMigrationStopNBDServer(driver, vm, mig);
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+ priv->migrationPort = 0;
if (flags & VIR_MIGRATE_PERSIST_DEST) {
virDomainDefPtr vmdef;
--
1.7.3.1.msysgit.0
Best Regards,
-WangYufei
11 years, 6 months
[libvirt] [PATCH] rpc: Fix getsockopt on Snow Leopard and lower
by Doug Goldstein
Since 5a468b38b6 we use SOL_LOCAL for the 2nd argument of getsockopt()
however Lion added the define SOL_LOCAL set to 0, which is the value to
the 2nd argument of getsockopt() for Unix sockets on Mac OS X. So
instead of using the define just pass 0 so we restore compatibility
with Snow Leopard and Leopard.
Reported at https://github.com/mxcl/homebrew/pull/23141
---
src/rpc/virnetsocket.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index a2823ef..8651a8b 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -1160,7 +1160,13 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
virObjectLock(sock);
# if defined(__APPLE__)
- if (getsockopt(sock->fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
+ /* Lion (10.7) and higher define the value to be passed to getsockopt()
+ * as SOL_LOCAL for Unix sockets, it is defined to 0. However
+ * Snow Leopard and lower did not have this define so you had to
+ * pass 0. To support the most cases we just pass 0, this behavior
+ * matches PostgreSQL and CUPS source code.
+ */
+ if (getsockopt(sock->fd, 0, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
# else
if (getsockopt(sock->fd, SOL_SOCKET, LOCAL_PEERCRED, &cr, &cr_len) < 0) {
# endif
--
1.8.1.5
11 years, 6 months