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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list