From 91b0ae89dd0fdab0ec9bd5a343db671d678da0a1 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 24 Apr 2006 18:21:29 +0000 Subject: [PATCH] * src/hash.c src/internal.h: add virGetDomainByID() to speed up some processing but not used yet * src/libvirt.c src/xen_internal.c src/xen_internal.h: added domain listing and number queries entry points based on the hypervisor which should speed up some processing as root. Daniel --- ChangeLog | 8 +++ src/hash.c | 44 ++++++++++++++ src/internal.h | 4 +- src/libvirt.c | 28 +++++++-- src/xen_internal.c | 148 +++++++++++++++++++++++++++++++++++++++++++-- src/xen_internal.h | 4 ++ 6 files changed, 226 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index bfbb11928e..239315ad1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Mon Apr 24 18:23:29 EDT 2006 Daniel Veillard + + * src/hash.c src/internal.h: add virGetDomainByID() to speed up + some processing but not used yet + * src/libvirt.c src/xen_internal.c src/xen_internal.h: added domain + listing and number queries entry points based on the hypervisor + which should speed up some processing as root. + Thu Apr 20 14:31:13 EDT 2006 Daniel Veillard * src/xend_internal.c: fix an uninitialized memory access in error diff --git a/src/hash.c b/src/hash.c index 69c070de2a..b231e7c5ed 100644 --- a/src/hash.c +++ b/src/hash.c @@ -723,3 +723,47 @@ done: return(ret); } +/** + * virGetDomainByID: + * @conn: the hypervisor connection + * @id: the ID number for the domain + * + * Lookup if the domain ID is already registered for that connection, + * if yes return a new pointer to it, if no return NULL + * + * Returns a pointer to the domain, or NULL if not found + */ +virDomainPtr +virGetDomainByID(virConnectPtr conn, int id) { + virDomainPtr ret = NULL, cur; + virHashEntryPtr iter, next; + virHashTablePtr table; + int key; + + if ((!VIR_IS_CONNECT(conn)) || (id < 0)) { + virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + xmlMutexLock(conn->domains_mux); + + table = conn->domains; + if ((table == NULL) || (table->nbElems == 0)) + goto done; + for (key = 0;key < table->size;key++) { + if (table->table[key].valid == 0) + continue; + iter = &(table->table[key]); + while (iter != NULL) { + next = iter->next; + cur = (virDomainPtr) iter->payload; + if ((cur != NULL) && (cur->handle == id)) { + ret = cur; + goto done; + } + iter = next; + } + } +done: + xmlMutexUnlock(conn->domains_mux); + return(ret); +} diff --git a/src/internal.h b/src/internal.h index 3e49b61fd1..a3d81e7a22 100644 --- a/src/internal.h +++ b/src/internal.h @@ -172,7 +172,7 @@ const char *__virErrorMsg(virErrorNumber error, const char *info); /************************************************************************ * * - * API for domain/connections (de)allocations * + * API for domain/connections (de)allocations and lookups * * * ************************************************************************/ @@ -183,6 +183,8 @@ virDomainPtr virGetDomain (virConnectPtr conn, const char *uuid); int virFreeDomain (virConnectPtr conn, virDomainPtr domain); +virDomainPtr virGetDomainByID(virConnectPtr conn, + int id); #ifdef __cplusplus } diff --git a/src/libvirt.c b/src/libvirt.c index 6692fb4347..1b5ee111b9 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -407,7 +407,7 @@ int virConnectListDomains(virConnectPtr conn, int *ids, int maxids) { int ret = -1; - unsigned int i; + int i; long id; char **idlist = NULL; @@ -421,8 +421,18 @@ virConnectListDomains(virConnectPtr conn, int *ids, int maxids) return (-1); } + /* Go though the driver registered entry points */ + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->listDomains != NULL)) { + ret = conn->drivers[i]->listDomains(conn, ids, maxids); + if (ret >= 0) + return(ret); + } + } + /* - * try first though the Xen Daemon + * try then though the Xen Daemon */ idlist = xenDaemonListDomains(conn); if (idlist != NULL) { @@ -454,6 +464,7 @@ int virConnectNumOfDomains(virConnectPtr conn) { int ret = -1; + int i; char **idlist = NULL; if (!VIR_IS_CONNECT(conn)) { @@ -461,9 +472,18 @@ virConnectNumOfDomains(virConnectPtr conn) return (-1); } - /* TODO: there must be a way to do that with an hypervisor call too ! */ + /* Go though the driver registered entry points */ + for (i = 0;i < conn->nb_drivers;i++) { + if ((conn->drivers[i] != NULL) && + (conn->drivers[i]->numOfDomains != NULL)) { + ret = conn->drivers[i]->numOfDomains(conn); + if (ret >= 0) + return(ret); + } + } + /* - * try first with Xend interface + * try then with Xend interface */ idlist = xenDaemonListDomains(conn); if (idlist != NULL) { diff --git a/src/xen_internal.c b/src/xen_internal.c index 8a99cf6204..cfcd2ecb68 100644 --- a/src/xen_internal.c +++ b/src/xen_internal.c @@ -48,8 +48,8 @@ static virDriver xenHypervisorDriver = { NULL, /* type */ xenHypervisorGetVersion, /* version */ NULL, /* nodeGetInfo */ - NULL, /* listDomains */ - NULL, /* numOfDomains */ + xenHypervisorListDomains, /* listDomains */ + xenHypervisorNumOfDomains, /* numOfDomains */ NULL, /* domainCreateLinux */ NULL, /* domainLookupByID */ NULL, /* domainLookupByUUID */ @@ -131,7 +131,7 @@ xenHypervisorOpen(virConnectPtr conn, const char *name, int flags) } conn->handle = ret; - return (ret); + return(0); } /** @@ -233,6 +233,144 @@ xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer) return(0); } +/** + * xenHypervisorNumOfDomains: + * @conn: pointer to the connection block + * + * Provides the number of active domains. + * + * Returns the number of domain found or -1 in case of error + */ +int +xenHypervisorNumOfDomains(virConnectPtr conn) +{ + dom0_op_t op; + dom0_getdomaininfo_t *dominfos; + int ret, nbids; + static int last_maxids = 2; + int maxids = last_maxids; + + if ((conn == NULL) || (conn->handle < 0)) + return (-1); + +retry: + dominfos = malloc(maxids * sizeof(dom0_getdomaininfo_t)); + if (dominfos == NULL) { + virXenError(VIR_ERR_NO_MEMORY, "failed to allocate %d domain info", + maxids); + return(-1); + } + + memset(dominfos, 0, sizeof(dom0_getdomaininfo_t) * maxids); + + if (mlock(dominfos, sizeof(dom0_getdomaininfo_t) * maxids) < 0) { + virXenError(VIR_ERR_XEN_CALL, " locking", + sizeof(dom0_getdomaininfo_t) * maxids); + free(dominfos); + return (-1); + } + + op.cmd = DOM0_GETDOMAININFOLIST; + op.u.getdomaininfolist.first_domain = (domid_t) 0; + op.u.getdomaininfolist.max_domains = maxids; + op.u.getdomaininfolist.buffer = dominfos; + op.u.getdomaininfolist.num_domains = maxids; + + ret = xenHypervisorDoOp(conn->handle, &op); + + if (munlock(dominfos, sizeof(dom0_getdomaininfo_t) * maxids) < 0) { + virXenError(VIR_ERR_XEN_CALL, " release", + sizeof(dom0_getdomaininfo_t) * maxids); + ret = -1; + } + + free(dominfos); + + if (ret < 0) + return (-1); + + nbids = op.u.getdomaininfolist.num_domains; + if (nbids == maxids) { + last_maxids *= 2; + maxids *= 2; + goto retry; + } + if ((nbids < 0) || (nbids > maxids)) + return(-1); + return(nbids); +} + +/** + * xenHypervisorListDomains: + * @conn: pointer to the connection block + * @ids: array to collect the list of IDs of active domains + * @maxids: size of @ids + * + * Collect the list of active domains, and store their ID in @maxids + * + * Returns the number of domain found or -1 in case of error + */ +int +xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids) +{ + dom0_op_t op; + dom0_getdomaininfo_t *dominfos; + int ret, nbids, i; + + if ((conn == NULL) || (conn->handle < 0) || + (ids == NULL) || (maxids < 1)) + return (-1); + + dominfos = malloc(maxids * sizeof(dom0_getdomaininfo_t)); + if (dominfos == NULL) { + virXenError(VIR_ERR_NO_MEMORY, "failed to allocate %d domain info", + maxids); + return(-1); + } + + memset(dominfos, 0, sizeof(dom0_getdomaininfo_t) * maxids); + memset(ids, 0, maxids * sizeof(int)); + + if (mlock(dominfos, sizeof(dom0_getdomaininfo_t) * maxids) < 0) { + virXenError(VIR_ERR_XEN_CALL, " locking", + sizeof(dom0_getdomaininfo_t) * maxids); + free(dominfos); + return (-1); + } + + op.cmd = DOM0_GETDOMAININFOLIST; + op.u.getdomaininfolist.first_domain = (domid_t) 0; + op.u.getdomaininfolist.max_domains = maxids; + op.u.getdomaininfolist.buffer = dominfos; + op.u.getdomaininfolist.num_domains = maxids; + + ret = xenHypervisorDoOp(conn->handle, &op); + + if (munlock(dominfos, sizeof(dom0_getdomaininfo_t) * maxids) < 0) { + virXenError(VIR_ERR_XEN_CALL, " release", + sizeof(dom0_getdomaininfo_t) * maxids); + ret = -1; + } + + if (ret < 0) { + free(dominfos); + return (-1); + } + + nbids = op.u.getdomaininfolist.num_domains; + if ((nbids < 0) || (nbids > maxids)) { + free(dominfos); + return(-1); + } + + for (i = 0;i < nbids;i++) { + ids[i] = dominfos[i].domain; + } + + free(dominfos); + return (nbids); +} + /** * xenHypervisorGetDomainInfo: * @domain: pointer to the domain block @@ -256,7 +394,7 @@ xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) memset(info, 0, sizeof(virDomainInfo)); memset(&dominfo, 0, sizeof(dom0_getdomaininfo_t)); - if (mlock(info, sizeof(dom0_getdomaininfo_t)) < 0) { + if (mlock(&dominfo, sizeof(dom0_getdomaininfo_t)) < 0) { virXenError(VIR_ERR_XEN_CALL, " locking", sizeof(dom0_getdomaininfo_t)); return (-1); @@ -271,7 +409,7 @@ xenHypervisorGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info) ret = xenHypervisorDoOp(domain->conn->handle, &op); - if (munlock(info, sizeof(dom0_getdomaininfo_t)) < 0) { + if (munlock(&dominfo, sizeof(dom0_getdomaininfo_t)) < 0) { virXenError(VIR_ERR_XEN_CALL, " release", sizeof(dom0_getdomaininfo_t)); ret = -1; diff --git a/src/xen_internal.h b/src/xen_internal.h index e47b8c5ab8..9870f29542 100644 --- a/src/xen_internal.h +++ b/src/xen_internal.h @@ -25,6 +25,10 @@ int xenHypervisorOpen (virConnectPtr conn, int xenHypervisorClose (virConnectPtr conn); int xenHypervisorGetVersion (virConnectPtr conn, unsigned long *hvVer); +int xenHypervisorNumOfDomains (virConnectPtr conn); +int xenHypervisorListDomains (virConnectPtr conn, + int *ids, + int maxids); int xenHypervisorDestroyDomain (virDomainPtr domain); int xenHypervisorResumeDomain (virDomainPtr domain); int xenHypervisorPauseDomain (virDomainPtr domain);