The xenstore database sometimes has stale domain IDs which are not
present in the hypervisor anymore. Filter these out to avoid causing
confusion
* src/xen/xs_internal.c: Filter domain IDs against HV's list
* src/xen/xen_hypervisor.h, src/xen/xen_hypervisor.c: Add new
xenHypervisorHasDomain() method for checking ID validity
---
src/xen/xen_hypervisor.c | 22 ++++++++++++++++++++++
src/xen/xen_hypervisor.h | 4 +++-
src/xen/xs_internal.c | 35 ++++++++++++++++++++++++++---------
3 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c
index 3aa3c30..6ab2431 100644
--- a/src/xen/xen_hypervisor.c
+++ b/src/xen/xen_hypervisor.c
@@ -2780,6 +2780,28 @@ xenHypervisorDomainGetOSType (virDomainPtr dom)
return strdup("linux");
}
+int
+xenHypervisorHasDomain(virConnectPtr conn,
+ int id)
+{
+ xenUnifiedPrivatePtr priv;
+ xen_getdomaininfo dominfo;
+
+ priv = (xenUnifiedPrivatePtr) conn->privateData;
+ if (priv->handle < 0)
+ return 0;
+
+ XEN_GETDOMAININFO_CLEAR(dominfo);
+
+ if (virXen_getdomaininfo(priv->handle, id, &dominfo) < 0)
+ return 0;
+
+ if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
+ return 0;
+
+ return 1;
+}
+
virDomainPtr
xenHypervisorLookupDomainByID(virConnectPtr conn,
int id)
diff --git a/src/xen/xen_hypervisor.h b/src/xen/xen_hypervisor.h
index 766f676..5971a90 100644
--- a/src/xen/xen_hypervisor.h
+++ b/src/xen/xen_hypervisor.h
@@ -23,7 +23,9 @@ int xenHypervisorInit (void);
virCapsPtr xenHypervisorMakeCapabilities (virConnectPtr conn);
/* The following calls are made directly by the Xen proxy: */
-
+int
+ xenHypervisorHasDomain(virConnectPtr conn,
+ int id);
virDomainPtr
xenHypervisorLookupDomainByID (virConnectPtr conn,
int id);
diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c
index 0fabcf8..c83cfda 100644
--- a/src/xen/xs_internal.c
+++ b/src/xen/xs_internal.c
@@ -545,8 +545,9 @@ int
xenStoreNumOfDomains(virConnectPtr conn)
{
unsigned int num;
- char **idlist;
- int ret = -1;
+ char **idlist = NULL, *endptr;
+ int i, ret = -1, realnum = 0;
+ long id;
xenUnifiedPrivatePtr priv;
if (conn == NULL) {
@@ -559,10 +560,22 @@ xenStoreNumOfDomains(virConnectPtr conn)
virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(-1);
}
+
idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
if (idlist) {
- free(idlist);
- ret = num;
+ for (i = 0; i < num; i++) {
+ id = strtol(idlist[i], &endptr, 10);
+ if ((endptr == idlist[i]) || (*endptr != 0))
+ goto out;
+
+ /* Sometimes xenstore has stale domain IDs, so filter
+ against the hypervisor's info */
+ if (xenHypervisorHasDomain(conn, (int)id))
+ realnum++;
+ }
+out:
+ VIR_FREE (idlist);
+ ret = realnum;
}
return(ret);
}
@@ -579,7 +592,7 @@ xenStoreNumOfDomains(virConnectPtr conn)
* Returns the number of domain found or -1 in case of error
*/
static int
-xenStoreDoListDomains(xenUnifiedPrivatePtr priv, int *ids, int maxids)
+xenStoreDoListDomains(virConnectPtr conn, xenUnifiedPrivatePtr priv, int *ids, int
maxids)
{
char **idlist = NULL, *endptr;
unsigned int num, i;
@@ -597,7 +610,11 @@ xenStoreDoListDomains(xenUnifiedPrivatePtr priv, int *ids, int
maxids)
id = strtol(idlist[i], &endptr, 10);
if ((endptr == idlist[i]) || (*endptr != 0))
goto out;
- ids[ret++] = (int) id;
+
+ /* Sometimes xenstore has stale domain IDs, so filter
+ against the hypervisor's info */
+ if (xenHypervisorHasDomain(conn, (int)id))
+ ids[ret++] = (int) id;
}
out:
@@ -629,7 +646,7 @@ xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
priv = (xenUnifiedPrivatePtr) conn->privateData;
xenUnifiedLock(priv);
- ret = xenStoreDoListDomains(priv, ids, maxids);
+ ret = xenStoreDoListDomains(conn, priv, ids, maxids);
xenUnifiedUnlock(priv);
return(ret);
@@ -1275,7 +1292,7 @@ retry:
virReportOOMError(NULL);
return -1;
}
- nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
+ nread = xenStoreDoListDomains(conn, priv, new_domids, new_domain_cnt);
if (nread != new_domain_cnt) {
// mismatch. retry this read
VIR_FREE(new_domids);
@@ -1356,7 +1373,7 @@ retry:
virReportOOMError(NULL);
return -1;
}
- nread = xenStoreDoListDomains(priv, new_domids, new_domain_cnt);
+ nread = xenStoreDoListDomains(conn, priv, new_domids, new_domain_cnt);
if (nread != new_domain_cnt) {
// mismatch. retry this read
VIR_FREE(new_domids);
--
1.6.2.5