When we migrate a guest from remote host to localhost by p2p, the libvirtd
on remote host will be deadlock. This patch fixes a bug and we can avoid
the deadlock with this patch.
The steps to reproduce this bug:
# virsh -c qemu+ssh://<remotehost IP>/system migrate --p2p <domain name>
qemu+ssh:///system
We connect dest host(qemu+ssh:///system) on source host, and the uri we pass
to source host is qemu+ssh:///system. And then we connect a wrong dest host.
Signed-off-by: Wen Congyang <wency(a)cn.fujitsu.com>
---
src/libvirt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index ee2495a..81a1bf8 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3533,22 +3533,71 @@ virDomainMigratePeer2Peer (virDomainPtr domain,
const char *uri,
unsigned long bandwidth)
{
+ xmlURIPtr tempxmluri = NULL;
+ char * tempuri = NULL;
+ int ret = -1;
+ char * hostname = NULL;
+
if (!domain->conn->driver->domainMigratePerform) {
virLibConnError (domain->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
virDispatchError(domain->conn);
return -1;
}
+ tempxmluri = xmlParseURI(uri);
+ if (!tempxmluri) {
+ virLibConnError (domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ virDispatchError(domain->conn);
+ goto out;
+ }
+ if (tempxmluri->server) {
+ tempuri = uri;
+ } else {
+ /*
+ * The uri will be passed to source host. If user inputs qemu:///system,
+ * the dest host is localhost. But we connect the dest host on source
+ * host(a remote host). So we should pass qemu://<dest hostname>/system
+ * to the source host.
+ */
+ hostname = virGetHostname(NULL);
+ if (!hostname) {
+ virDispatchError(domain->conn);
+ goto out;
+ }
+
+ if (STRPREFIX(hostname, "localhost")) {
+ virLibConnError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ _("hostname on destination resolved to localhost, but
migration requires an FQDN"));
+ virDispatchError(domain->conn);
+ goto out;
+ }
+
+ tempxmluri->server = hostname;
+ tempuri = strdup((char *)xmlSaveUri(tempxmluri));
+ if (!tempuri) {
+ virReportOOMError();
+ virDispatchError(domain->conn);
+ goto out;
+ }
+ }
+
/* Perform the migration. The driver isn't supposed to return
* until the migration is complete.
*/
- return domain->conn->driver->domainMigratePerform(domain,
+ ret = domain->conn->driver->domainMigratePerform(domain,
NULL, /* cookie */
0, /* cookielen */
- uri,
+ tempuri,
flags,
dname,
bandwidth);
+
+out:
+ VIR_FREE(hostname);
+ if (tempuri && tempuri != uri)
+ VIR_FREE(tempuri);
+
+ return ret;
}
--
1.7.1