The API queries huge page info in the host and reports it back to the caller. This may be handy for management application to decide whether to run a domain with huge pages enabled or not. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- daemon/remote.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ include/libvirt/libvirt.h.in | 6 +++++ src/driver.h | 7 ++++++ src/libvirt.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/remote/remote_driver.c | 48 +++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 19 +++++++++++++++- src/remote_protocol-structs | 13 +++++++++++ 8 files changed, 205 insertions(+), 1 deletion(-) diff --git a/daemon/remote.c b/daemon/remote.c index 34c96c9..95ff973 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6115,6 +6115,60 @@ remoteDispatchDomainGetTime(virNetServerPtr server ATTRIBUTE_UNUSED, return rv; } +static int remoteDispatchNodeHugeTlb(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_node_huge_tlb_args *args, + remote_node_huge_tlb_ret *ret) +{ + virTypedParameterPtr params = NULL; + int nparams = 0; + int rv = -1; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (args->nparams > REMOTE_NODE_MEMORY_PARAMETERS_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large")); + goto cleanup; + } + if (args->nparams && VIR_ALLOC_N(params, args->nparams) < 0) + goto cleanup; + nparams = args->nparams; + + if (virNodeHugeTLB(priv->conn, args->type, params, &nparams, args->flags) < 0) + goto cleanup; + + /* In this case, we need to send back the number of parameters + * supported + */ + if (args->nparams == 0) { + ret->nparams = nparams; + goto success; + } + + if (remoteSerializeTypedParameters(params, nparams, + &ret->params.params_val, + &ret->params.params_len, + args->flags) < 0) + goto cleanup; + + + success: + rv = 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virTypedParamsFree(params, nparams); + return rv; +} + + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 260c971..cb1cad9 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -858,6 +858,12 @@ int virNodeSetMemoryParameters(virConnectPtr conn, int nparams, unsigned int flags); +int virNodeHugeTLB(virConnectPtr conn, + int type, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); + /* * node CPU map */ diff --git a/src/driver.h b/src/driver.h index 5ac89d6..4acde08 100644 --- a/src/driver.h +++ b/src/driver.h @@ -1070,6 +1070,12 @@ typedef int virTypedParameterPtr params, int nparams, unsigned int flags); +typedef int +(*virDrvNodeHugeTLB)(virConnectPtr conn, + int type, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); typedef int (*virDrvNodeGetCPUMap)(virConnectPtr conn, @@ -1376,6 +1382,7 @@ struct _virDriver { virDrvDomainGetMetadata domainGetMetadata; virDrvNodeGetMemoryParameters nodeGetMemoryParameters; virDrvNodeSetMemoryParameters nodeSetMemoryParameters; + virDrvNodeHugeTLB nodeHugeTLB; virDrvNodeGetCPUMap nodeGetCPUMap; virDrvDomainFSTrim domainFSTrim; virDrvDomainSendProcessSignal domainSendProcessSignal; diff --git a/src/libvirt.c b/src/libvirt.c index f01b6dd..de20b0c 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -7561,6 +7561,60 @@ virNodeSetMemoryParameters(virConnectPtr conn, /** + * virNodeHugeTLB: + * @conn: pointer to the hypervisor connection + * @type: type + * @params: pointer to memory parameter object + * (return value, allocated by the caller) + * @nparams: pointer to number of memory parameters; input and output + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Get information about host's huge pages. On input, @nparams + * gives the size of the @params array; on output, @nparams gives + * how many slots were filled with parameter information, which + * might be less but will not exceed the input value. + * + * As a special case, calling with @params as NULL and @nparams + * as 0 on input will cause @nparams on output to contain the + * number of parameters supported by the hypervisor. The caller + * should then allocate @params array, i.e. + * (sizeof(@virTypedParameter) * @nparams) bytes and call the API + * again. See virDomainGetMemoryParameters() for an equivalent + * usage example. + * + * Returns 0 in case of success, and -1 in case of failure. + */ +int +virNodeHugeTLB(virConnectPtr conn, + int type, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + VIR_DEBUG("conn=%p, type=%d, params=%p, nparams=%p, flags=%x", + conn, type, params, nparams, flags); + + virResetLastError(); + + virCheckNonNullArgGoto(nparams, error); + virCheckNonNegativeArgGoto(*nparams, error); + + if (conn->driver->nodeHugeTLB) { + int ret; + ret = conn->driver->nodeHugeTLB(conn, type, params, nparams, flags); + if (ret < 0) + goto error; + return ret; + } + virReportUnsupportedError(); + + error: + virDispatchError(conn); + return -1; +} + + +/** * virDomainGetSchedulerType: * @domain: pointer to domain object * @nparams: pointer to number of scheduler parameters, can be NULL diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index cce6bdf..0339e70 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -658,5 +658,10 @@ LIBVIRT_1.2.5 { virDomainSetTime; } LIBVIRT_1.2.3; +LIBVIRT_1.2.6 { + global: + virNodeHugeTLB; +} LIBVIRT_1.2.5; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 85fe597..9136b78 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7469,6 +7469,53 @@ remoteDomainGetTime(virDomainPtr dom, } +static int +remoteNodeHugeTLB(virConnectPtr conn, + int type, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + int rv = -1; + remote_node_huge_tlb_args args; + remote_node_huge_tlb_ret ret; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + args.type = type; + args.nparams = *nparams; + args.flags = flags; + + memset(&ret, 0, sizeof(ret)); + if (call(conn, priv, 0, REMOTE_PROC_NODE_HUGE_TLB, + (xdrproc_t) xdr_remote_node_huge_tlb_args, (char *) &args, + (xdrproc_t) xdr_remote_node_huge_tlb_ret, (char *) &ret) == -1) + goto done; + + if (*nparams == 0) { + *nparams = ret.nparams; + rv = 0; + goto cleanup; + } + + if (remoteDeserializeTypedParameters(ret.params.params_val, + ret.params.params_len, + REMOTE_NODE_MEMORY_PARAMETERS_MAX, + ¶ms, + nparams) < 0) + goto cleanup; + + rv = 0; + + cleanup: + xdr_free((xdrproc_t) xdr_remote_node_huge_tlb_ret, (char *) &ret); + done: + remoteDriverUnlock(priv); + return rv; +} + + /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, @@ -7805,6 +7852,7 @@ static virDriver remote_driver = { .domainFSThaw = remoteDomainFSThaw, /* 1.2.5 */ .domainGetTime = remoteDomainGetTime, /* 1.2.5 */ .domainSetTime = remoteDomainSetTime, /* 1.2.5 */ + .nodeHugeTLB = remoteNodeHugeTLB, /* 1.2.6 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 1f9d583..4d6cc15 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2836,6 +2836,17 @@ struct remote_node_get_memory_parameters_ret { int nparams; }; +struct remote_node_huge_tlb_args { + int type; + int nparams; + unsigned int flags; +}; + +struct remote_node_huge_tlb_ret { + remote_typed_param params<REMOTE_NODE_MEMORY_PARAMETERS_MAX>; + int nparams; +}; + struct remote_node_get_cpu_map_args { int need_map; int need_online; @@ -5338,5 +5349,11 @@ enum remote_procedure { * @generate: both * @acl: domain:set_time */ - REMOTE_PROC_DOMAIN_SET_TIME = 338 + REMOTE_PROC_DOMAIN_SET_TIME = 338, + + /** + * @generate: none + * @acl: connect:read + */ + REMOTE_PROC_NODE_HUGE_TLB = 339 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 5b22049..e3fcdea 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2271,6 +2271,18 @@ struct remote_node_get_memory_parameters_ret { } params; int nparams; }; +struct remote_node_huge_tlb_args { + int type; + int nparams; + u_int flags; +}; +struct remote_node_huge_tlb_ret { + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + int nparams; +}; struct remote_node_get_cpu_map_args { int need_map; int need_online; @@ -2802,4 +2814,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_FSTHAW = 336, REMOTE_PROC_DOMAIN_GET_TIME = 337, REMOTE_PROC_DOMAIN_SET_TIME = 338, + REMOTE_PROC_NODE_HUGE_TLB = 339, }; -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list