Add new virsh command line `nodecachestats` to expose the cache usage on a node. Signed-off-by: Eli Qiao <liyong.qiao@xxxxxxxxx> --- src/libvirt_private.syms | 3 ++- src/qemu/qemu_driver.c | 12 ++++++++++ src/util/virresctrl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virresctrl.h | 8 +++++++ tools/virsh-host.c | 49 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9cfffb8..75a4c98 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2323,13 +2323,14 @@ virRandomInt; # util/virresctrl.h virResCtrlAvailable; +virResCtrlCacheGetStats; virResCtrlGet; virResCtrlInit; virResCtrlSetCacheBanks; virResCtrlTypeFromString; virResCtrlTypeToString; virResCtrlUpdate; -# + # util/virrotatingfile.h virRotatingFileReaderConsume; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f11ae2..4677406 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18285,6 +18285,17 @@ qemuNodeGetCPUStats(virConnectPtr conn, return virHostCPUGetStats(cpuNum, params, nparams, flags); } +static int +qemuNodeGetCacheStats(virConnectPtr conn, + virNodeCacheStatsPtr params, + int *nparams, + unsigned int flags) +{ + if (virNodeGetCacheStatsEnsureACL(conn) < 0) + return -1; + + return virResCtrlCacheGetStats(params, nparams, flags); +} static int qemuNodeGetMemoryStats(virConnectPtr conn, @@ -20391,6 +20402,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainMemoryPeek = qemuDomainMemoryPeek, /* 0.4.4 */ .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */ .nodeGetCPUStats = qemuNodeGetCPUStats, /* 0.9.3 */ + .nodeGetCacheStats = qemuNodeGetCacheStats, /* 3.1.0 */ .nodeGetMemoryStats = qemuNodeGetMemoryStats, /* 0.9.3 */ .nodeGetCellsFreeMemory = qemuNodeGetCellsFreeMemory, /* 0.4.4 */ .nodeGetFreeMemory = qemuNodeGetFreeMemory, /* 0.4.4 */ diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 16c01a2..97f7e84 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -1034,3 +1034,65 @@ virResCtrlGet(int type) { return &resctrlall[type]; } + +int virResCtrlCacheGetStats(virNodeCacheStatsPtr params, + int *nparams, + unsigned int flags) +{ + virCheckFlags(0, -1); + size_t i, j, k; + char *value; + int rc = -1; + int lockfd; + + if (*nparams == 0) { + for (i = 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) + *nparams += resctrlall[i].num_banks; + } + } + if (params == NULL) + return 0; + + if ((lockfd = open(RESCTRL_DIR, O_RDONLY)) < 0) + goto cleanup; + + if (VIR_RESCTRL_LOCK(lockfd, LOCK_SH) < 0) { + virReportSystemError(errno, _("Unable to lock '%s'"), RESCTRL_DIR); + goto cleanup; + } + if (virResCtrlScan() < 0) { + VIR_ERROR(_("Failed to scan resctrl domain dir")); + goto cleanup; + } + + virResCtrlRefreshSchemata(); + + if ((rc = virResCtrlFlushDomainToSysfs(domainall.domains)) < 0) + goto cleanup; + + k = 0; + + for (i = 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) { + for (j = 0; j < resctrlall[i].num_banks; j++) { + + if (virAsprintf(&value, "%s.%zu", + resctrlall[i].name, j) < 0) + goto cleanup; + + if (virStrcpyStatic((¶ms[k])->field, value) == NULL) + goto cleanup; + + (¶ms[k++])->value = resctrlall[i].cache_banks[j].cache_left; + } + } + } + + rc = 0; + + cleanup: + VIR_FREE(value); + VIR_RESCTRL_UNLOCK(lockfd); + return rc; +} diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 968e0dc..eef5370 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -80,9 +80,17 @@ struct _virResCtrl { }; bool virResCtrlAvailable(void); + int virResCtrlInit(void); + virResCtrlPtr virResCtrlGet(int); + int virResCtrlSetCacheBanks(virDomainCachetunePtr, unsigned char *, pid_t *, int); + int virResCtrlUpdate(unsigned char *); + +int virResCtrlCacheGetStats(virNodeCacheStatsPtr params, + int *nparams, + unsigned int flags); #endif diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 24ebde2..c90bd2e 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -946,6 +946,49 @@ cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd) VIR_FREE(params); return ret; } +/* "nodecachestats" command + */ +static const vshCmdInfo info_nodecachestats[] = { + {.name = "help", + .data = N_("Prints cache stats of the node.") + }, + {.name = "desc", + .data = N_("Returns cache stats of the node, in kilobytes.") + }, + {.name = NULL} +}; + +static bool +cmdNodeCacheStats(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + virshControlPtr priv = ctl->privData; + virNodeCacheStatsPtr params; + int nparams = 0; + size_t i; + bool ret = false; + + if (virNodeGetCacheStats(priv->conn, NULL, &nparams, 0) != 0) { + vshError(ctl, "%s", + _("Unable to get number of cache stats")); + return false; + } + if (nparams == 0) { + /* nothing to output */ + return true; + } + + params = vshCalloc(ctl, nparams, sizeof(*params)); + if (virNodeGetCacheStats(priv->conn, params, &nparams, 0) != 0) { + vshError(ctl, "%s", _("Unable to get node cache stats")); + goto cleanup; + } + + for (i = 0; i < nparams; i++) + vshPrint(ctl, "%s: %llu KiB\n", params[i].field, params[i].value); + + cleanup: + return ret; +} /* * "nodesuspend" command @@ -1455,6 +1498,12 @@ const vshCmdDef hostAndHypervisorCmds[] = { .info = info_nodememstats, .flags = 0 }, + {.name = "nodecachestats", + .handler = cmdNodeCacheStats, + .opts = NULL, + .info = info_nodecachestats, + .flags = 0 + }, {.name = "nodesuspend", .handler = cmdNodeSuspend, .opts = opts_node_suspend, -- 1.9.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list