diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index d6c9c57661d5bbe047b5a5aa5e2c0097ec9d628b..fe2ff86a4350e016f7c295f6994b6b200cdc6dfe 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1142,20 +1142,33 @@ static int xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags) { GET_PRIVATE(dom->conn); - int i, ret; + int ret; - if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { - xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), - flags); + virCheckFlags(VIR_DOMAIN_VCPU_LIVE | + VIR_DOMAIN_VCPU_CONFIG | + VIR_DOMAIN_VCPU_MAXIMUM, -1); + + /* Exactly one of LIVE or CONFIG must be set. */ + if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) { + xenUnifiedError(VIR_ERR_INVALID_ARG, + _("invalid flag combination: (0x%x)"), flags); return -1; } - for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) - if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) { - ret = drivers[i]->domainGetMaxVcpus (dom); - if (ret != 0) return ret; - } + if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) { + ret = xenDaemonDomainGetVcpusFlags(dom, flags); + if (ret != -2) + return ret; + } + if (priv->opened[XEN_UNIFIED_XM_OFFSET]) { + ret = xenXMDomainGetVcpusFlags(dom, flags); + if (ret != -2) + return ret; + } + if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM)) + return xenHypervisorGetVcpuMax(dom); + xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__); return -1; } diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index dfc64150fb16e34b2dd2a4b1bfd427b7dd8b0c5b..3642296c7f095ffac86b324b76606413148ea698 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -3619,6 +3619,58 @@ xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu, "cpumap", mapstr, NULL)); } +/** + * xenDaemonDomainGetVcpusFlags: + * @domain: pointer to domain object + * @flags: bitwise-ORd from virDomainVcpuFlags + * + * Extract information about virtual CPUs of domain according to flags. + * + * Returns the number of vcpus on success, -1 if an error message was + * issued, and -2 if the unified driver should keep trying. + + */ +int +xenDaemonDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) +{ + struct sexpr *root; + int ret; + xenUnifiedPrivatePtr priv; + + if (domain == NULL || domain->conn == NULL || domain->name == NULL) { + virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + priv = (xenUnifiedPrivatePtr) domain->conn->privateData; + + /* If xendConfigVersion is 2, then we can only report _LIVE (and + * xm_internal reports _CONFIG). If it is 3, then _LIVE and + * _CONFIG are always in sync for a running system. */ + if (domain->id < 0 && priv->xendConfigVersion < 3) + return -2; + if (domain->id < 0 && (flags & VIR_DOMAIN_VCPU_LIVE)) { + virXendError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain not active")); + return -1; + } + + root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name); + if (root == NULL) + return -1; + + ret = sexpr_int(root, "domain/vcpus"); + if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) { + int vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail")); + if (vcpus) + ret = MIN(vcpus, ret); + } + if (!ret) + ret = -2; + sexpr_free(root); + return ret; +} + /** * virDomainGetVcpus: * @domain: pointer to domain object, or NULL for Domain0 diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h index c757716a46d9aafd72a47e9492f8530c94520fb5..923cebd8f0d7971d5fe05b8b7cac0e86ff00167e 100644 --- a/src/xen/xend_internal.h +++ b/src/xen/xend_internal.h @@ -155,6 +155,8 @@ int xenDaemonDomainPinVcpu (virDomainPtr domain, unsigned int vcpu, unsigned char *cpumap, int maplen); +int xenDaemonDomainGetVcpusFlags (virDomainPtr domain, + unsigned int flags); int xenDaemonDomainGetVcpus (virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index f7121ab2a9c7dc799a5c34bc4348d8685807fd7f..4ea4245f64b224c0e80ed50352b9ecba8f4598b9 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1670,6 +1670,53 @@ cleanup: return ret; } +/** + * xenXMDomainGetVcpusFlags: + * @domain: pointer to domain object + * @flags: bitwise-ORd from virDomainVcpuFlags + * + * Extract information about virtual CPUs of domain according to flags. + * + * Returns the number of vcpus on success, -1 if an error message was + * issued, and -2 if the unified driver should keep trying. + */ +int +xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) +{ + xenUnifiedPrivatePtr priv; + const char *filename; + xenXMConfCachePtr entry; + int ret = -2; + + if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { + xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (domain->id != -1) + return -2; + if (flags & VIR_DOMAIN_VCPU_LIVE) { + xenXMError(VIR_ERR_OPERATION_FAILED, "%s", _("domain not active")); + return -1; + } + + priv = domain->conn->privateData; + xenUnifiedLock(priv); + + if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) + goto cleanup; + + if (!(entry = virHashLookup(priv->configCache, filename))) + goto cleanup; + + ret = ((flags & VIR_DOMAIN_VCPU_MAXIMUM) ? entry->def->maxvcpus + : entry->def->vcpus); + +cleanup: + xenUnifiedUnlock(priv); + return ret; +} + /** * xenXMDomainPinVcpu: * @domain: pointer to domain object diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h index 3ad34564295dad49b0c850481a049f77717c4f69..3295fbdef880e6f847dd8d1a311d139e2f42ea99 100644 --- a/src/xen/xm_internal.h +++ b/src/xen/xm_internal.h @@ -45,6 +45,7 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory); int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain); int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus); +int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags); int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu, unsigned char *cpumap, int maplen); virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname);