diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 22d53e53beeb3169162d7bdba5c37cb9600f32c3..f4ea36e8ffdcf31cdb34ac723f895fab8b43a0e8 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -468,7 +468,8 @@ nodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, long long mem; if (numa_node_size64(n, &mem) < 0) { nodeReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Failed to query NUMA free memory")); + _("Failed to query NUMA free memory for node: %d"), + n); goto cleanup; } freeMems[numCells++] = mem; diff --git a/tools/virsh.c b/tools/virsh.c index 50d5e33967b8680a1c4ad17eb7064824ad62328d..ce275f1b9fd5d688df771c86f83fee9f5964d559 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2283,9 +2283,15 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) int ret; int cell, cell_given; unsigned long long memory; - unsigned long long *nodes = NULL; + xmlNodePtr *nodes = NULL; + unsigned long nodes_cnt; + unsigned long *nodes_id = NULL; + unsigned long long *nodes_free = NULL; int all_given; - virNodeInfo info; + int i; + char *cap_xml = NULL; + xmlDocPtr xml = NULL; + xmlXPathContextPtr ctxt = NULL; if (!vshConnectionUsability(ctl, ctl->conn)) @@ -2301,32 +2307,57 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) } if (all_given) { - if (virNodeGetInfo(ctl->conn, &info) < 0) { - vshError(ctl, "%s", _("failed to get NUMA nodes count")); + cap_xml = virConnectGetCapabilities(ctl->conn); + if (!cap_xml) { + vshError(ctl, "%s", _("unable to get node capabilities")); goto cleanup; } - if (!info.nodes) { - vshError(ctl, "%s", _("no NUMA nodes present")); - goto cleanup; - } + xml = xmlReadDoc((const xmlChar *) cap_xml, "node.xml", NULL, + XML_PARSE_NOENT | XML_PARSE_NONET | + XML_PARSE_NOWARNING); - if (VIR_ALLOC_N(nodes, info.nodes) < 0) { - vshError(ctl, "%s", _("could not allocate memory")); + if (!xml) { + vshError(ctl, "%s", _("unable to get node capabilities")); goto cleanup; } - ret = virNodeGetCellsFreeMemory(ctl->conn, nodes, 0, info.nodes); - if (ret != info.nodes) { + ctxt = xmlXPathNewContext(xml); + nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell", + ctxt, &nodes); + + if (nodes_cnt == -1) { vshError(ctl, "%s", _("could not get information about " - "all NUMA nodes")); + "NUMA topology")); goto cleanup; } + nodes_free = vshCalloc(ctl, nodes_cnt, sizeof(*nodes_free)); + nodes_id = vshCalloc(ctl, nodes_cnt, sizeof(*nodes_id)); + + for (i = 0; i < nodes_cnt; i++) { + unsigned long id; + char *val = virXMLPropString(nodes[i], "id"); + if (virStrToLong_ul(val, NULL, 10, &id)) { + vshError(ctl, "%s", _("conversion from string failed")); + VIR_FREE(val); + goto cleanup; + } + VIR_FREE(val); + nodes_id[i]=id; + ret = virNodeGetCellsFreeMemory(ctl->conn, &(nodes_free[i]), id, 1); + if (ret != 1) { + vshError(ctl, _("failed to get free memory for NUMA node " + "number: %lu"), id); + goto cleanup; + } + } + memory = 0; - for (cell = 0; cell < info.nodes; cell++) { - vshPrint(ctl, "%5d: %10llu kB\n", cell, (nodes[cell]/1024)); - memory += nodes[cell]; + for (cell = 0; cell < nodes_cnt; cell++) { + vshPrint(ctl, "%5lu: %10llu kB\n", nodes_id[cell], + (nodes_free[cell]/1024)); + memory += nodes_free[cell]; } vshPrintExtra(ctl, "--------------------\n"); @@ -2351,7 +2382,13 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) func_ret = TRUE; cleanup: + xmlXPathFreeContext(ctxt); + if (xml) + xmlFreeDoc(xml); VIR_FREE(nodes); + VIR_FREE(nodes_free); + VIR_FREE(nodes_id); + VIR_FREE(cap_xml); return func_ret; }