Some drivers don't expose available huge page sizes in the
capabilities XML. For instance, LXC driver is one of those.
This has a downside that when virsh is trying to get
aggregated info on free pages per all NUMA nodes, it fails.
The problem is that the virNodeGetFreePages() API expects
caller to pass an array of page sizes he is interested in.
In virsh, this array is filled from the capabilities from
'/capabilities/host/cpu/pages' XPath. As said, in LXC
there's no such XPath and therefore virsh fails currently.
But hey, we can fallback: the page sizes are exposed under
'/capabilities/host/topology/cells/cell/pages'. The page
size can be collected from there, and voilĂ the command
works again. But now we must make sure that there are no
duplicates in the array passed to the public API. Otherwise
we won't get as beautiful output as we are getting now.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
tools/virsh-host.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 66f7fd9..28f6da1 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -285,6 +285,15 @@ static const vshCmdOptDef opts_freepages[] = {
{.name = NULL}
};
+static int
+vshPageSizeSorter(const void *a, const void *b)
+{
+ unsigned int pa = *(unsigned int *)a;
+ unsigned int pb = *(unsigned int *)b;
+
+ return pa - pb;
+}
+
static bool
cmdFreepages(vshControl *ctl, const vshCmd *cmd)
{
@@ -326,9 +335,15 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd)
nodes_cnt = virXPathNodeSet("/capabilities/host/cpu/pages", ctxt,
&nodes);
if (nodes_cnt <= 0) {
- vshError(ctl, "%s", _("could not get information about
"
- "supported page sizes"));
- goto cleanup;
+ /* Some drivers don't export page sizes under the
+ * XPath above. Do another trick to get them */
+ nodes_cnt =
virXPathNodeSet("/capabilities/host/topology/cells/cell/pages",
+ ctxt, &nodes);
+ if (nodes_cnt <= 0) {
+ vshError(ctl, "%s", _("could not get information about
"
+ "supported page sizes"));
+ goto cleanup;
+ }
}
pagesize = vshCalloc(ctl, nodes_cnt, sizeof(*pagesize));
@@ -345,6 +360,22 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd)
VIR_FREE(val);
}
+ /* Here, if we've done the trick few lines above,
+ * @pagesize array will contain duplicates. We should
+ * remove them otherwise not very nice output will be
+ * produced. */
+ qsort(pagesize, nodes_cnt, sizeof(*pagesize), vshPageSizeSorter);
+
+ for (i = 0; i < nodes_cnt - 1; ) {
+ if (pagesize[i] == pagesize[i + 1]) {
+ memmove(pagesize + i, pagesize + i + 1,
+ (nodes_cnt - i + 1) * sizeof(*pagesize));
+ nodes_cnt--;
+ } else {
+ i++;
+ }
+ }
+
npages = nodes_cnt;
VIR_FREE(nodes);
} else {
--
2.3.6