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(a)redhat.com>
---
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