This patch expose a public API virNodeCacheStats to query cache stats on a host. Signed-off-by: Eli Qiao <liyong.qiao@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list