[libvirt] [PATCH v2 6/7] virsh: Expose virNodeGetFreePages

Michal Privoznik mprivozn at redhat.com
Mon Jun 16 15:08:29 UTC 2014


The new API is exposed under 'freepages' command.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 tools/virsh-host.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/virsh.pod    |   8 +++
 2 files changed, 175 insertions(+)

diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index 8091437..2d6cb00 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -193,6 +193,167 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd)
     return ret;
 }
 
+
+/*
+ * "freepages" command
+ */
+static const vshCmdInfo info_freepages[] = {
+    {.name = "help",
+     .data = N_("NUMA free memory")
+    },
+    {.name = "desc",
+     .data = N_("display available free memory for the NUMA cell.")
+    },
+    {.name = NULL}
+};
+
+static const vshCmdOptDef opts_freepages[] = {
+    {.name = "cellno",
+     .type = VSH_OT_INT,
+     .help = N_("NUMA cell number")
+    },
+    {.name = "pagesize",
+     .type = VSH_OT_INT,
+     .help = N_("page size (in kibibites)")
+    },
+    {.name = "all",
+     .type = VSH_OT_BOOL,
+     .help = N_("show free pages for all NUMA cells")
+    },
+    {.name = NULL}
+};
+
+static bool
+cmdFreepages(vshControl *ctl, const vshCmd *cmd)
+{
+    bool ret = false;
+    unsigned int npages;
+    unsigned int *pagesize = NULL;
+    int cell;
+    unsigned long long *counts = NULL;
+    size_t i, j;
+    xmlNodePtr *nodes = NULL;
+    int nodes_cnt;
+    char *cap_xml = NULL;
+    xmlDocPtr doc = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    bool all = vshCommandOptBool(cmd, "all");
+    bool cellno = vshCommandOptBool(cmd, "cellno");
+
+    VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
+
+    if (all) {
+        if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) {
+            vshError(ctl, "%s", _("unable to get node capabilities"));
+            goto cleanup;
+        }
+
+        if (!(doc = virXMLParseStringCtxt(cap_xml, _("capabilities"), &ctxt))) {
+            vshError(ctl, "%s", _("unable to parse node capabilities"));
+            goto cleanup;
+        }
+
+        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;
+        }
+
+        pagesize = vshMalloc(ctl, nodes_cnt * sizeof(*pagesize));
+
+        for (i = 0; i < nodes_cnt; i++) {
+            char *val = virXMLPropString(nodes[i], "size");
+
+            if (virStrToLong_ui(val, NULL, 10, &pagesize[i]) < 0) {
+                vshError(ctl, _("unable to parse page size: %s"), val);
+                VIR_FREE(val);
+                goto cleanup;
+            }
+
+            VIR_FREE(val);
+        }
+
+        npages = nodes_cnt;
+        VIR_FREE(nodes);
+
+        counts = vshMalloc(ctl, npages * sizeof(*counts));
+
+        nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell",
+                                    ctxt, &nodes);
+        for (i = 0; i < nodes_cnt; i++) {
+            char *val = virXMLPropString(nodes[i], "id");
+
+            if (virStrToLong_i(val, NULL, 10, &cell) < 0) {
+                vshError(ctl, _("unable to parse numa node id: %s"), val);
+                VIR_FREE(val);
+                goto cleanup;
+            }
+            VIR_FREE(val);
+
+            if (virNodeGetFreePages(ctl->conn, npages, pagesize,
+                                    cell, 1, counts, 0) < 0)
+                goto cleanup;
+
+            vshPrint(ctl, _("Node %d:\n"), cell);
+            for (j = 0; j < npages; j++) {
+                vshPrint(ctl, "%uKiB: %lld\n", pagesize[j], counts[j]);
+            }
+            vshPrint(ctl, "%c", '\n');
+        }
+
+    } else {
+        if (!cellno) {
+            vshError(ctl, "%s", _("missing cellno argument"));
+            goto cleanup;
+        }
+
+        if (vshCommandOptInt(cmd, "cellno", &cell) < 0) {
+            vshError(ctl, "%s", _("Invalid cellno argument"));
+            goto cleanup;
+        }
+
+        if (cell < -1) {
+            vshError(ctl, "%s", _("cell number must be non-negative integer or -1"));
+            goto cleanup;
+        }
+
+        pagesize = vshMalloc(ctl, sizeof(*pagesize));
+        if (vshCommandOptScaledInt(cmd, "pagesize", (unsigned long long *) pagesize,
+                                   1, UINT_MAX) < 0) {
+            vshError(ctl, "%s", _("page size has to be a number"));
+            goto cleanup;
+        }
+
+        /* page size is expected in kibibytes */
+        pagesize[0] /= 1024;
+
+        if (!pagesize[0]) {
+            vshError(ctl, "%s", _("page size must be at least 1KiB"));
+            goto cleanup;
+        }
+
+        counts = vshMalloc(ctl, sizeof(*counts));
+
+        if (virNodeGetFreePages(ctl->conn, 1, pagesize, cell, 1, counts, 0) < 0)
+            goto cleanup;
+
+        vshPrint(ctl, "%uKiB: %lld\n", *pagesize, counts[0]);
+    }
+
+    ret = true;
+ cleanup:
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(doc);
+    VIR_FREE(cap_xml);
+    VIR_FREE(nodes);
+    VIR_FREE(counts);
+    VIR_FREE(pagesize);
+    return ret;
+}
+
+
 /*
  * "maxvcpus" command
  */
@@ -977,6 +1138,12 @@ const vshCmdDef hostAndHypervisorCmds[] = {
      .info = info_freecell,
      .flags = 0
     },
+    {.name = "freepages",
+     .handler = cmdFreepages,
+     .opts = opts_freepages,
+     .info = info_freepages,
+     .flags = 0
+    },
     {.name = "hostname",
      .handler = cmdHostname,
      .opts = NULL,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 35cf878..0cc89ad 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -511,6 +511,14 @@ cell and the total free memory on the machine.  Finally, with a
 numeric argument or with --cellno plus a cell number it will display
 the free memory for the specified cell only.
 
+=item B<freepages> [{ [I<--cellno>] I<cellno> [I<--pagesize>] I<pagesize> |
+    I<--all> }]
+
+Prints the available amount of pages within a NUMA cell. I<cellno> refers
+to the NUMA cell you're interested in. I<pagesize> is a scaled integer (see
+B<NOTES> above).  Alternatively, if I<--all> is used, info on each possible
+combination of NUMA cell and page size is printed out.
+
 =item B<cpu-baseline> I<FILE> [I<--features>]
 
 Compute baseline CPU which will be supported by all host CPUs given in <file>.
-- 
1.8.5.5




More information about the libvir-list mailing list