From: Shaju Abraham <shaju.abraham(a)nutanix.com>
At the time of registration, the close callback routines are inserted
to a hash table using the UUID as index. Since UUID is unique in a host,
a single hash entry is suffice to represent a domain object. But in the
case of local migration, the UUID is shared between the source and
destination VMs. This creates hash collision since both source and
destination VMs are on same host. Inorder to uniquely identify the
source and destination VMs , the domain id is appeneded to the UUID
to generate a unique hash key. The routines are modified to handle
the above change.
Signed-off-by: Shaju Abraham <shaju.abraham(a)nutanix.com>
---
src/util/virclosecallbacks.c | 48 +++++++++++++++++++++++++++---------
src/util/virclosecallbacks.h | 3 +++
2 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/src/util/virclosecallbacks.c b/src/util/virclosecallbacks.c
index 200577e18e..a8ab46d4d7 100644
--- a/src/util/virclosecallbacks.c
+++ b/src/util/virclosecallbacks.c
@@ -24,6 +24,7 @@
#include "virclosecallbacks.h"
#include "virlog.h"
#include "virobject.h"
+#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -34,6 +35,7 @@ typedef virDriverCloseDef *virDriverCloseDefPtr;
struct _virDriverCloseDef {
virConnectPtr conn;
virCloseCallback cb;
+ virDomainObjPtr vm;
};
struct _virCloseCallbacks {
@@ -85,7 +87,6 @@ virCloseCallbacksDispose(void *obj)
virHashFree(closeCallbacks->list);
}
-
int
virCloseCallbacksSet(virCloseCallbacksPtr closeCallbacks,
virDomainObjPtr vm,
@@ -93,6 +94,7 @@ virCloseCallbacksSet(virCloseCallbacksPtr closeCallbacks,
virCloseCallback cb)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *uniqstr = NULL;
virDriverCloseDefPtr closeDef;
int ret = -1;
@@ -100,9 +102,10 @@ virCloseCallbacksSet(virCloseCallbacksPtr closeCallbacks,
VIR_DEBUG("vm=%s, uuid=%s, conn=%p, cb=%p",
vm->def->name, uuidstr, conn, cb);
+ uniqstr = g_strdup_printf("%s%d", uuidstr, vm->def->id);
virObjectLock(closeCallbacks);
- closeDef = virHashLookup(closeCallbacks->list, uuidstr);
+ closeDef = virHashLookup(closeCallbacks->list, uniqstr);
if (closeDef) {
if (closeDef->conn != conn) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -125,7 +128,8 @@ virCloseCallbacksSet(virCloseCallbacksPtr closeCallbacks,
closeDef->conn = conn;
closeDef->cb = cb;
- if (virHashAddEntry(closeCallbacks->list, uuidstr, closeDef) < 0) {
+ closeDef->vm = vm;
+ if (virHashAddEntry(closeCallbacks->list, uniqstr, closeDef) < 0) {
VIR_FREE(closeDef);
goto cleanup;
}
@@ -145,6 +149,7 @@ virCloseCallbacksUnset(virCloseCallbacksPtr closeCallbacks,
virCloseCallback cb)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *uniqstr = NULL;
virDriverCloseDefPtr closeDef;
int ret = -1;
@@ -152,9 +157,10 @@ virCloseCallbacksUnset(virCloseCallbacksPtr closeCallbacks,
VIR_DEBUG("vm=%s, uuid=%s, cb=%p",
vm->def->name, uuidstr, cb);
+ uniqstr = g_strdup_printf("%s%d", uuidstr, vm->def->id);
virObjectLock(closeCallbacks);
- closeDef = virHashLookup(closeCallbacks->list, uuidstr);
+ closeDef = virHashLookup(closeCallbacks->list, uniqstr);
if (!closeDef)
goto cleanup;
@@ -165,7 +171,7 @@ virCloseCallbacksUnset(virCloseCallbacksPtr closeCallbacks,
goto cleanup;
}
- if (virHashRemoveEntry(closeCallbacks->list, uuidstr) < 0)
+ if (virHashRemoveEntry(closeCallbacks->list, uniqstr) < 0)
goto cleanup;
virObjectUnref(vm);
@@ -183,16 +189,18 @@ virCloseCallbacksGet(virCloseCallbacksPtr closeCallbacks,
virConnectPtr conn)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *uniqstr = NULL;
virDriverCloseDefPtr closeDef;
virCloseCallback cb = NULL;
virUUIDFormat(vm->def->uuid, uuidstr);
VIR_DEBUG("vm=%s, uuid=%s, conn=%p",
vm->def->name, uuidstr, conn);
+ uniqstr = g_strdup_printf("%s%d", uuidstr, vm->def->id);
virObjectLock(closeCallbacks);
- closeDef = virHashLookup(closeCallbacks->list, uuidstr);
+ closeDef = virHashLookup(closeCallbacks->list, uniqstr);
if (closeDef && (!conn || closeDef->conn == conn))
cb = closeDef->cb;
@@ -207,15 +215,17 @@ virCloseCallbacksGetConn(virCloseCallbacksPtr closeCallbacks,
virDomainObjPtr vm)
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *uniqstr = NULL;
virDriverCloseDefPtr closeDef;
virConnectPtr conn = NULL;
virUUIDFormat(vm->def->uuid, uuidstr);
VIR_DEBUG("vm=%s, uuid=%s", vm->def->name, uuidstr);
+ uniqstr = g_strdup_printf("%s%d", uuidstr, vm->def->id);
virObjectLock(closeCallbacks);
- closeDef = virHashLookup(closeCallbacks->list, uuidstr);
+ closeDef = virHashLookup(closeCallbacks->list, uniqstr);
if (closeDef)
conn = closeDef->conn;
@@ -231,6 +241,7 @@ typedef virCloseCallbacksListEntry *virCloseCallbacksListEntryPtr;
struct _virCloseCallbacksListEntry {
unsigned char uuid[VIR_UUID_BUFLEN];
virCloseCallback callback;
+ virDomainObjPtr vm;
};
typedef struct _virCloseCallbacksList virCloseCallbacksList;
@@ -274,6 +285,7 @@ virCloseCallbacksGetOne(void *payload,
memcpy(data->list->entries[data->list->nentries - 1].uuid,
uuid, VIR_UUID_BUFLEN);
data->list->entries[data->list->nentries - 1].callback =
closeDef->cb;
+ data->list->entries[data->list->nentries - 1].vm = closeDef->vm;
return 0;
}
@@ -302,8 +314,18 @@ virCloseCallbacksGetForConn(virCloseCallbacksPtr closeCallbacks,
return list;
}
-
-
+virDomainObjPtr virGetMatchingDomain(virDomainObjListPtr domains,
+ unsigned char *uuidstr, virDomainObjPtr dom)
+{
+ virDomainObjPtr vm = NULL;
+ vm = virDomainObjListFindByUUID(domains, uuidstr);
+ if (!vm || vm != dom) {
+ vm = virDomainObjListFindByUUIDRemote(domains, uuidstr);
+ if (!vm || vm != dom)
+ return NULL;
+ }
+ return vm;
+}
void
virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
virConnectPtr conn,
@@ -329,8 +351,10 @@ virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
for (i = 0; i < list->nentries; i++) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *uniqstr = NULL;
virUUIDFormat(list->entries[i].uuid, uuidstr);
- virHashRemoveEntry(closeCallbacks->list, uuidstr);
+ uniqstr = g_strdup_printf("%s%d", uuidstr,
list->entries[i].vm->def->id);
+ virHashRemoveEntry(closeCallbacks->list, uniqstr);
}
virObjectUnlock(closeCallbacks);
@@ -338,8 +362,8 @@ virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
virDomainObjPtr vm;
/* Grab a ref and lock to the vm */
- if (!(vm = virDomainObjListFindByUUID(domains,
- list->entries[i].uuid))) {
+ if (!(vm = virGetMatchingDomain(domains,
+ list->entries[i].uuid, list->entries[i].vm))) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(list->entries[i].uuid, uuidstr);
VIR_DEBUG("No domain object with UUID %s", uuidstr);
diff --git a/src/util/virclosecallbacks.h b/src/util/virclosecallbacks.h
index 98fc2c4a94..253ecab6bc 100644
--- a/src/util/virclosecallbacks.h
+++ b/src/util/virclosecallbacks.h
@@ -48,3 +48,6 @@ virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
virConnectPtr conn,
virDomainObjListPtr domains,
void *opaque);
+
+virDomainObjPtr virGetMatchingDomain(virDomainObjListPtr domains,
+ unsigned char *uuidstr, virDomainObjPtr dom);
--
2.24.1