diff --git a/daemon/remote.c b/daemon/remote.c index 8d04fc7dfb..aa726cf211 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1047,6 +1047,75 @@ cleanup: return rv; } +static int +remoteDispatchDomainGetVcpupinInfo(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_get_vcpupin_info_args *args, + remote_domain_get_vcpupin_info_ret *ret) +{ + virDomainPtr dom = NULL; + unsigned char *cpumaps = NULL; + int num; + int rv = -1; + + if (!conn) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(dom = get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (args->ncpumaps > REMOTE_VCPUINFO_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("ncpumaps > REMOTE_VCPUINFO_MAX")); + goto cleanup; + } + + if (INT_MULTIPLY_OVERFLOW(args->ncpumaps, args->maplen) || + args->ncpumaps * args->maplen > REMOTE_CPUMAPS_MAX) { + virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); + goto cleanup; + } + + /* Allocate buffers to take the results. */ + if (args->maplen > 0 && + VIR_ALLOC_N(cpumaps, args->ncpumaps * args->maplen) < 0) + goto no_memory; + + if ((num = virDomainGetVcpupinInfo(dom, + args->ncpumaps, + cpumaps, + args->maplen, + args->flags)) < 0) + goto cleanup; + + ret->num = num; + /* Don't need to allocate/copy the cpumaps if we make the reasonable + * assumption that unsigned char and char are the same size. + * Note that remoteDispatchClientRequest will free. + */ + ret->cpumaps.cpumaps_len = args->ncpumaps * args->maplen; + ret->cpumaps.cpumaps_val = (char *) cpumaps; + cpumaps = NULL; + + rv = 0; + +cleanup: + if (rv < 0) + remoteDispatchError(rerr); + VIR_FREE(cpumaps); + if (dom) + virDomainFree(dom); + return rv; + +no_memory: + virReportOOMError(); + goto cleanup; +} + static int remoteDispatchDomainGetVcpus(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index f2edf436bb..84a5eab4ac 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2141,6 +2141,79 @@ done: return rv; } +static int +remoteDomainGetVcpupinInfo (virDomainPtr domain, + int ncpumaps, + unsigned char *cpumaps, + int maplen, + unsigned int flags) +{ + int rv = -1; + int i; + remote_domain_get_vcpupin_info_args args; + remote_domain_get_vcpupin_info_ret ret; + struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); + + if (ncpumaps > REMOTE_VCPUINFO_MAX) { + remoteError(VIR_ERR_RPC, + _("vCPU count exceeds maximum: %d > %d"), + ncpumaps, REMOTE_VCPUINFO_MAX); + goto done; + } + + if (INT_MULTIPLY_OVERFLOW(ncpumaps, maplen) || + ncpumaps * maplen > REMOTE_CPUMAPS_MAX) { + remoteError(VIR_ERR_RPC, + _("vCPU map buffer length exceeds maximum: %d > %d"), + ncpumaps * maplen, REMOTE_CPUMAPS_MAX); + goto done; + } + + make_nonnull_domain (&args.dom, domain); + args.ncpumaps = ncpumaps; + args.maplen = maplen; + args.flags = flags; + + memset (&ret, 0, sizeof ret); + + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUPIN_INFO, + (xdrproc_t) xdr_remote_domain_get_vcpupin_info_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_get_vcpupin_info_ret, + (char *) &ret) == -1) + goto done; + + if (ret.num > ncpumaps) { + remoteError(VIR_ERR_RPC, + _("host reports too many vCPUs: %d > %d"), + ret.num, ncpumaps); + goto cleanup; + } + + if (ret.cpumaps.cpumaps_len > ncpumaps * maplen) { + remoteError(VIR_ERR_RPC, + _("host reports map buffer length exceeds maximum: %d > %d"), + ret.cpumaps.cpumaps_len, ncpumaps * maplen); + goto cleanup; + } + + memset (cpumaps, 0, ncpumaps * maplen); + + for (i = 0; i < ret.cpumaps.cpumaps_len; ++i) + cpumaps[i] = ret.cpumaps.cpumaps_val[i]; + + rv = ret.num; + +cleanup: + xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpupin_info_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + static int remoteDomainGetVcpus (virDomainPtr domain, virVcpuInfoPtr info, @@ -6392,6 +6465,7 @@ static virDriver remote_driver = { .domainGetVcpusFlags = remoteDomainGetVcpusFlags, /* 0.8.5 */ .domainPinVcpu = remoteDomainPinVcpu, /* 0.3.0 */ .domainPinVcpuFlags = remoteDomainPinVcpuFlags, /* 0.9.3 */ + .domainGetVcpupinInfo = remoteDomainGetVcpupinInfo, /* 0.9.3 */ .domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */ .domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */ .domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 35f6ee59e1..ee08b825ad 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -903,6 +903,18 @@ struct remote_domain_pin_vcpu_flags_args { unsigned int flags; }; +struct remote_domain_get_vcpupin_info_args { + remote_nonnull_domain dom; + int ncpumaps; + int maplen; + unsigned int flags; +}; + +struct remote_domain_get_vcpupin_info_ret { + opaque cpumaps; + int num; +}; + struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo; @@ -2379,7 +2391,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SEND_KEY = 226, /* autogen autogen */ REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen */ REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen */ - REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229 /* autogen autogen */ + REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen */ + REMOTE_PROC_DOMAIN_GET_VCPUPIN_INFO = 230 /* skipgen skipgen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 81bd0331fd..be98135ae6 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -580,6 +580,19 @@ struct remote_domain_pin_vcpu_flags_args { } cpumap; u_int flags; }; +struct remote_domain_get_vcpupin_info_args { + remote_nonnull_domain dom; + int ncpumaps; + int maplen; + u_int flags; +}; +struct remote_domain_get_vcpupin_info_ret { + struct { + u_int cpumaps_len; + char * cpumaps_val; + } cpumaps; + int num; +}; struct remote_domain_get_vcpus_args { remote_nonnull_domain dom; int maxinfo;