This patch expose a public API virNodeCacheStats to query cache stats
on a host.
Signed-off-by: Eli Qiao <liyong.qiao(a)intel.com>
---
daemon/remote.c | 67 ++++++++++++++++++++++++++++++++++++++++++
include/libvirt/libvirt-host.h | 32 ++++++++++++++++++++
src/driver-hypervisor.h | 7 +++++
src/libvirt-host.c | 41 ++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/remote/remote_driver.c | 52 ++++++++++++++++++++++++++++++++
src/remote/remote_protocol.x | 25 +++++++++++++++-
src/remote_protocol-structs | 16 ++++++++++
8 files changed, 240 insertions(+), 1 deletion(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index f2b9b9a..af291a7 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -7079,3 +7079,70 @@ remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors,
}
return -1;
}
+
+ static int
+remoteDispatchNodeGetCacheStats(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_node_get_cache_stats_args *args,
+ remote_node_get_cache_stats_ret *ret)
+{
+ virNodeCacheStatsPtr params = NULL;
+ size_t i;
+ int nparams = 0;
+ unsigned int flags;
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not
open"));
+ goto cleanup;
+ }
+
+ flags = args->flags;
+
+ if (args->nparams && VIR_ALLOC_N(params, args->nparams) < 0)
+ goto cleanup;
+ nparams = args->nparams;
+
+ if (virNodeGetCacheStats(priv->conn, params, &nparams, flags) < 0)
+ goto cleanup;
+
+ /* In this case, we need to send back the number of stats
+ * supported
+ */
+ if (args->nparams == 0) {
+ ret->nparams = nparams;
+ goto success;
+ }
+
+ /* Serialise the memory parameters. */
+ ret->params.params_len = nparams;
+ if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
+ goto cleanup;
+
+ for (i = 0; i < nparams; ++i) {
+ /* remoteDispatchClientRequest will free this: */
+ if (VIR_STRDUP(ret->params.params_val[i].field, params[i].field) < 0)
+ goto cleanup;
+
+ ret->params.params_val[i].value = params[i].value;
+ }
+
+ success:
+ rv = 0;
+
+ cleanup:
+ if (rv < 0) {
+ virNetMessageSaveError(rerr);
+ if (ret->params.params_val) {
+ for (i = 0; i < nparams; i++)
+ VIR_FREE(ret->params.params_val[i].field);
+ VIR_FREE(ret->params.params_val);
+ }
+ }
+ VIR_FREE(params);
+ return rv;
+}
diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 07b5d15..222f361 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -140,6 +140,32 @@ struct _virSecurityModel {
*/
typedef virSecurityModel *virSecurityModelPtr;
+/**
+ * VIR_NODE_CACHE_STATS_FIELD_LENGTH:
+ *
+ * Macro providing the field length of virNodeCacheStats
+ */
+
+# define VIR_NODE_CACHE_STATS_FIELD_LENGTH 16
+
+/**
+ *
+ * virNodeCacheStats is all the cache stats on a host.
+ */
+
+typedef struct _virNodeCacheStats virNodeCacheStats;
+
+struct _virNodeCacheStats {
+ char field[VIR_NODE_CACHE_STATS_FIELD_LENGTH];
+ unsigned long long value;
+};
+
+/**
+ * a virNodeCacheStatsPtr is a pointer to a virNodeCacheStats.
+ */
+
+typedef virNodeCacheStats *virNodeCacheStatsPtr;
+
/* data types related to virNodePtr */
@@ -603,6 +629,12 @@ int virNodeSuspendForDuration (virConnectPtr
conn,
unsigned long long duration,
unsigned int flags);
+int virNodeGetCacheStats (virConnectPtr conn,
+ virNodeCacheStatsPtr params,
+ int *nparams,
+ unsigned int flags);
+
+
/*
* NUMA support
*/
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 51af732..2f81e74 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -578,6 +578,12 @@ typedef int
unsigned int flags);
typedef int
+(*virDrvNodeGetCacheStats)(virConnectPtr conn,
+ virNodeCacheStatsPtr params,
+ int *nparams,
+ unsigned int flags);
+
+typedef int
(*virDrvNodeGetCellsFreeMemory)(virConnectPtr conn,
unsigned long long *freeMems,
int startCell,
@@ -1452,6 +1458,7 @@ struct _virHypervisorDriver {
virDrvConnectSetKeepAlive connectSetKeepAlive;
virDrvConnectIsAlive connectIsAlive;
virDrvNodeSuspendForDuration nodeSuspendForDuration;
+ virDrvNodeGetCacheStats nodeGetCacheStats;
virDrvDomainGetPerfEvents domainGetPerfEvents;
virDrvDomainSetPerfEvents domainSetPerfEvents;
virDrvDomainSetBlockIoTune domainSetBlockIoTune;
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 335798a..87c1279 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -679,6 +679,47 @@ virNodeSuspendForDuration(virConnectPtr conn,
return -1;
}
+/*
+ * virNodeGetCacheStats:
+ * @conn: pointer to the hypervisor connection
+ * @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 all node cache usage stats.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ *
+*/
+
+int virNodeGetCacheStats(virConnectPtr conn,
+ virNodeCacheStatsPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ VIR_DEBUG("conn=%p, params=%p, nparams=%d, flags=%x",
+ conn, params, nparams ? *nparams : -1, flags);
+ virResetLastError();
+
+ virCheckConnectReturn(conn, -1);
+ virCheckNonNullArgGoto(nparams, error);
+ virCheckNonNegativeArgGoto(*nparams, error);
+
+ if (conn->driver->nodeGetCacheStats) {
+ int ret;
+ ret = conn->driver->nodeGetCacheStats(conn, params, nparams, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(conn);
+ return -1;
+
+}
/*
* virNodeGetMemoryParameters:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 62885ac..05a087b 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -751,6 +751,7 @@ LIBVIRT_3.0.0 {
virStorageVolGetInfoFlags;
virConnectSecretEventRegisterAny;
virConnectSecretEventDeregisterAny;
+ virNodeGetCacheStats;
} LIBVIRT_2.2.0;
# .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 59d74a2..bd67b15 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1708,6 +1708,57 @@ remoteNodeGetCellsFreeMemory(virConnectPtr conn,
}
static int
+remoteNodeGetCacheStats(virConnectPtr conn,
+ virNodeCacheStatsPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ int rv = -1;
+ size_t i;
+ remote_node_get_cache_stats_args args;
+ remote_node_get_cache_stats_ret ret;
+ struct private_data *priv = conn->privateData;
+
+ remoteDriverLock(priv);
+
+ args.nparams = *nparams;
+ args.flags = flags;
+
+ memset(&ret, 0, sizeof(ret));
+ if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_CACHE_STATS,
+ (xdrproc_t) xdr_remote_node_get_cache_stats_args, (char *) &args,
+ (xdrproc_t) xdr_remote_node_get_cache_stats_ret, (char *) &ret) == -1)
+ goto done;
+
+ if (*nparams == 0) {
+ *nparams = ret.nparams;
+ rv = 0;
+ goto cleanup;
+ }
+
+ *nparams = ret.params.params_len;
+
+ /* Deserialise the result. */
+ for (i = 0; i < *nparams; ++i) {
+ if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Stats %s too big for destination"),
+ ret.params.params_val[i].field);
+ goto cleanup;
+ }
+ params[i].value = ret.params.params_val[i].value;
+ }
+
+ rv = 0;
+
+ cleanup:
+ xdr_free((xdrproc_t) xdr_remote_node_get_cache_stats_ret, (char *) &ret);
+ done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+static int
remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids)
{
int rv = -1;
@@ -8320,6 +8371,7 @@ static virHypervisorDriver hypervisor_driver = {
.nodeGetMemoryStats = remoteNodeGetMemoryStats, /* 0.9.3 */
.nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory, /* 0.3.3 */
.nodeGetFreeMemory = remoteNodeGetFreeMemory, /* 0.3.3 */
+ .nodeGetCacheStats = remoteNodeGetCacheStats, /* 3.0.0 */
.connectDomainEventRegister = remoteConnectDomainEventRegister, /* 0.5.0 */
.connectDomainEventDeregister = remoteConnectDomainEventDeregister, /* 0.5.0 */
.domainMigratePrepare2 = remoteDomainMigratePrepare2, /* 0.5.0 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 6445685..6941760 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -121,6 +121,9 @@ const REMOTE_NODE_CPU_STATS_MAX = 16;
/* Upper limit on list of node memory stats. */
const REMOTE_NODE_MEMORY_STATS_MAX = 16;
+/* Upper limit on list of node cache stats */
+const REMOTE_NODE_CACHE_STATS_MAX = 16;
+
/* Upper limit on list of block stats. */
const REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX = 16;
@@ -394,6 +397,11 @@ struct remote_node_get_memory_stats {
unsigned hyper value;
};
+struct remote_node_get_cache_stats {
+ remote_nonnull_string field;
+ unsigned hyper value;
+};
+
struct remote_domain_disk_error {
remote_nonnull_string disk;
int error;
@@ -492,6 +500,16 @@ struct remote_node_get_info_ret { /* insert@1 */
int threads;
};
+struct remote_node_get_cache_stats_args {
+ int nparams;
+ u_int flags;
+};
+
+struct remote_node_get_cache_stats_ret {
+ remote_node_get_cache_stats params<REMOTE_NODE_CACHE_STATS_MAX>;
+ int nparams;
+};
+
struct remote_connect_get_capabilities_ret {
remote_nonnull_string capabilities;
};
@@ -6018,6 +6036,11 @@ enum remote_procedure {
* @generate: both
* @acl: none
*/
- REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383
+ REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383,
+ /**
+ * @generate: none
+ * @acl: connect:read
+ */
+ REMOTE_PROC_NODE_GET_CACHE_STATS = 384
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 0360600..4639a09 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -94,6 +94,10 @@ struct remote_node_get_memory_stats {
remote_nonnull_string field;
uint64_t value;
};
+struct remote_node_get_cache_stats {
+ remote_nonnull_string field;
+ uint64_t value;
+};
struct remote_domain_disk_error {
remote_nonnull_string disk;
int error;
@@ -2380,6 +2384,17 @@ struct remote_node_get_cpu_map_ret {
u_int online;
int ret;
};
+struct remote_node_get_cache_stats_args {
+ int nparams;
+ u_int flags;
+};
+struct remote_node_get_cache_stats_ret {
+ struct {
+ u_int paramms_len;
+ remote_node_get_cache_stats * params_val;
+ } params;
+ int nparams;
+};
struct remote_domain_fstrim_args {
remote_nonnull_domain dom;
remote_string mountPoint;
@@ -3210,4 +3225,5 @@ enum remote_procedure {
REMOTE_PROC_CONNECT_SECRET_EVENT_DEREGISTER_ANY = 381,
REMOTE_PROC_SECRET_EVENT_LIFECYCLE = 382,
REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED = 383,
+ REMOTE_PROC_NODE_GET_CACHE_STATS = 384,
};
--
1.9.1