[libvirt] [PATCH 2/5] virCaps: expose huge page info

Michal Privoznik mprivozn at redhat.com
Tue Jun 10 17:21:12 UTC 2014


There are two places where you'll find info on huge pages. The first
one is under <cpu/> element, where all supported huge page sizes are
listed. Then the second one is under each <cell/> element which refers
to concrete NUMA node. At this place, the size of huge page's pool is
reported. So the capabilities XML looks something like this:

<capabilities>

  <host>
    <uuid>01281cda-f352-cb11-a9db-e905fe22010c</uuid>
    <cpu>
      <arch>x86_64</arch>
      <model>Westmere</model>
      <vendor>Intel</vendor>
      <topology sockets='1' cores='1' threads='1'/>
      ...
      <pages unit='KiB' size='1048576'/>
      <pages unit='KiB' size='2048'/>
    </cpu>
    ...
    <topology>
      <cells num='4'>
        <cell id='0'>
          <memory unit='KiB'>4054408</memory>
          <pages unit='KiB' size='1048576'>1</pages>
          <pages unit='KiB' size='2048'>3</pages>
          <distances/>
          <cpus num='1'>
            <cpu id='0' socket_id='0' core_id='0' siblings='0'/>
          </cpus>
        </cell>
        <cell id='1'>
          <memory unit='KiB'>4071072</memory>
          <pages unit='KiB' size='1048576'>2</pages>
          <pages unit='KiB' size='2048'>1024</pages>
          <distances/>
          <cpus num='1'>
            <cpu id='1' socket_id='0' core_id='0' siblings='1'/>
          </cpus>
        </cell>
        ...
      </cells>
    </topology>
    ...
  </host>

  <guest/>

</capabilities>

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 docs/schemas/capability.rng  | 21 +++++++++++++++++++++
 src/conf/capabilities.c      | 25 ++++++++++++++++++++++---
 src/conf/capabilities.h      | 15 ++++++++++++++-
 src/libxl/libxl_conf.c       |  1 +
 src/nodeinfo.c               | 41 ++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_capabilities.c | 29 ++++++++++++++++++++++++++++-
 src/test/test_driver.c       |  2 +-
 src/xen/xend_internal.c      |  1 +
 tests/vircaps2xmltest.c      |  3 ++-
 tests/vircapstest.c          |  1 +
 10 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 0c95c05..ee6cb2e 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -118,6 +118,9 @@
         <empty/>
       </element>
     </zeroOrMore>
+    <zeroOrMore>
+      <ref name='hugepagesElem'/>
+    </zeroOrMore>
   </define>
 
   <define name='power_management'>
@@ -188,6 +191,10 @@
         <ref name='memory'/>
       </optional>
 
+      <zeroOrMore>
+        <ref name='hugepagesElem'/>
+      </zeroOrMore>
+
       <optional>
         <element name='distances'>
           <zeroOrMore>
@@ -416,4 +423,18 @@
       <param name='pattern'>[a-zA-Z0-9\-_]+</param>
     </data>
   </define>
+
+  <define name='hugepagesElem'>
+    <element name='pages'>
+      <optional>
+        <attribute name='unit'>
+          <ref name='unit'/>
+        </attribute>
+      </optional>
+      <attribute name='size'>
+        <ref name='unsignedInt'/>
+      </attribute>
+      <ref name='unsignedInt'/>
+    </element>
+  </define>
 </grammar>
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 954456b..c773752 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -108,6 +108,7 @@ virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
 
     VIR_FREE(cell->cpus);
     VIR_FREE(cell->siblings);
+    VIR_FREE(cell->hugepages);
     VIR_FREE(cell);
 }
 
@@ -223,6 +224,7 @@ virCapabilitiesDispose(void *object)
     }
     VIR_FREE(caps->host.secModels);
 
+    VIR_FREE(caps->host.hugePagesSize);
     virCPUDefFree(caps->host.cpu);
 }
 
@@ -281,6 +283,8 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
  * @cpus: array of CPU definition structures, the pointer is stolen
  * @nsiblings: number of sibling NUMA nodes
  * @siblings: info on sibling NUMA nodes
+ * @nhugepages: number of hugepages at node @num
+ * @hugepages: info on each single huge page
  *
  * Registers a new NUMA cell for a host, passing in a
  * array of CPU IDs belonging to the cell
@@ -292,7 +296,9 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
                                int ncpus,
                                virCapsHostNUMACellCPUPtr cpus,
                                int nsiblings,
-                               virCapsHostNUMACellSiblingInfoPtr siblings)
+                               virCapsHostNUMACellSiblingInfoPtr siblings,
+                               int nhugepages,
+                               virCapsHostNUMACellHugePageInfoPtr hugepages)
 {
     virCapsHostNUMACellPtr cell;
 
@@ -303,12 +309,14 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
     if (VIR_ALLOC(cell) < 0)
         return -1;
 
-    cell->ncpus = ncpus;
     cell->num = num;
     cell->mem = mem;
+    cell->ncpus = ncpus;
     cell->cpus = cpus;
-    cell->siblings = siblings;
     cell->nsiblings = nsiblings;
+    cell->siblings = siblings;
+    cell->nhugepages = nhugepages;
+    cell->hugepages = hugepages;
 
     caps->host.numaCell[caps->host.nnumaCell++] = cell;
 
@@ -773,6 +781,12 @@ virCapabilitiesFormatNUMATopology(virBufferPtr buf,
             virBufferAsprintf(buf, "<memory unit='KiB'>%llu</memory>\n",
                               cells[i]->mem);
 
+        for (j = 0; j < cells[i]->nhugepages; j++) {
+            virBufferAsprintf(buf, "<pages unit='KiB' size='%u'>%zu</pages>\n",
+                              cells[i]->hugepages[j].size,
+                              cells[i]->hugepages[j].avail);
+        }
+
         if (cells[i]->nsiblings) {
             virBufferAddLit(buf, "<distances>\n");
             virBufferAdjustIndent(buf, 2);
@@ -856,6 +870,11 @@ virCapabilitiesFormatXML(virCapsPtr caps)
     }
     virCPUDefFormatBuf(&buf, caps->host.cpu, 0);
 
+    for (i = 0; i < caps->host.nhugePagesSize; i++) {
+        virBufferAsprintf(&buf, "<pages unit='KiB' size='%u'/>\n",
+                          caps->host.hugePagesSize[i]);
+    }
+
     virBufferAdjustIndent(&buf, -2);
     virBufferAddLit(&buf, "</cpu>\n");
 
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 53a83c9..384e256 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -102,6 +102,13 @@ struct _virCapsHostNUMACellSiblingInfo {
     unsigned int distance;  /* distance to the node */
 };
 
+typedef struct _virCapsHostNUMACellHugePageInfo virCapsHostNUMACellHugePageInfo;
+typedef virCapsHostNUMACellHugePageInfo *virCapsHostNUMACellHugePageInfoPtr;
+struct _virCapsHostNUMACellHugePageInfo {
+    unsigned int size;      /* huge page size in kibibytes */
+    size_t avail;           /* the size of pool */
+};
+
 typedef struct _virCapsHostNUMACell virCapsHostNUMACell;
 typedef virCapsHostNUMACell *virCapsHostNUMACellPtr;
 struct _virCapsHostNUMACell {
@@ -111,6 +118,8 @@ struct _virCapsHostNUMACell {
     virCapsHostNUMACellCPUPtr cpus;
     int nsiblings;
     virCapsHostNUMACellSiblingInfoPtr siblings;
+    int nhugepages;
+    virCapsHostNUMACellHugePageInfoPtr hugepages;
 };
 
 typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel;
@@ -152,6 +161,8 @@ struct _virCapsHost {
     virCapsHostSecModelPtr secModels;
 
     virCPUDefPtr cpu;
+    int nhugePagesSize;             /* size of hugePagesSize array */
+    unsigned int *hugePagesSize;    /* huge page sizes support on the system */
     unsigned char host_uuid[VIR_UUID_BUFLEN];
 };
 
@@ -206,7 +217,9 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
                                int ncpus,
                                virCapsHostNUMACellCPUPtr cpus,
                                int nsiblings,
-                               virCapsHostNUMACellSiblingInfoPtr siblings);
+                               virCapsHostNUMACellSiblingInfoPtr siblings,
+                               int nhugepages,
+                               virCapsHostNUMACellHugePageInfoPtr hugepages);
 
 
 extern int
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index cec37d6..eca51a1 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -210,6 +210,7 @@ libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps)
         if (virCapabilitiesAddHostNUMACell(caps, i,
                                            numa_info[i].size / 1024,
                                            nr_cpus_node[i], cpus[i],
+                                           0, NULL,
                                            0, NULL) < 0) {
             virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
                                                         nr_cpus_node[i]);
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 5eef42e..fbf2e3c 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -1646,6 +1646,7 @@ nodeCapsInitNUMAFake(virCapsPtr caps ATTRIBUTE_UNUSED)
     if (virCapabilitiesAddHostNUMACell(caps, 0,
                                        nodeinfo.memory,
                                        ncpus, cpus,
+                                       0, NULL,
                                        0, NULL) < 0)
         goto error;
 
@@ -1795,6 +1796,36 @@ virNodeCapsGetSiblingInfo(int node,
     return ret;
 }
 
+static int
+virNodeCapsGetHugePagesInfo(int node,
+                            virCapsHostNUMACellHugePageInfoPtr *hugepages,
+                            int *nhugepages)
+{
+    int ret = -1;
+    unsigned int *pages_size = NULL, *pages_avail = NULL;
+    size_t npages, i;
+
+    if (virNumaGetHugePages(node, &pages_size,
+                            &pages_avail, NULL, &npages) < 0)
+        goto cleanup;
+
+    if (VIR_ALLOC_N(*hugepages, npages) < 0)
+        goto cleanup;
+    *nhugepages = npages;
+
+    for (i = 0; i < npages; i++) {
+        (*hugepages)[i].size = pages_size[i];
+        (*hugepages)[i].avail = pages_avail[i];
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(pages_avail);
+    VIR_FREE(pages_size);
+    return ret;
+}
+
 int
 nodeCapsInitNUMA(virCapsPtr caps)
 {
@@ -1804,6 +1835,8 @@ nodeCapsInitNUMA(virCapsPtr caps)
     virBitmapPtr cpumap = NULL;
     virCapsHostNUMACellSiblingInfoPtr siblings = NULL;
     int nsiblings;
+    virCapsHostNUMACellHugePageInfoPtr hugepages = NULL;
+    int nhugepages;
     int ret = -1;
     int ncpus = 0;
     int cpu;
@@ -1846,17 +1879,22 @@ nodeCapsInitNUMA(virCapsPtr caps)
         if (virNodeCapsGetSiblingInfo(n, &siblings, &nsiblings) < 0)
             goto cleanup;
 
+        if (virNodeCapsGetHugePagesInfo(n, &hugepages, &nhugepages) < 0)
+            goto cleanup;
+
         /* Detect the amount of memory in the numa cell in KiB */
         virNumaGetNodeMemory(n, &memory, NULL);
         memory >>= 10;
 
         if (virCapabilitiesAddHostNUMACell(caps, n, memory,
                                            ncpus, cpus,
-                                           nsiblings, siblings) < 0)
+                                           nsiblings, siblings,
+                                           nhugepages, hugepages) < 0)
             goto cleanup;
 
         cpus = NULL;
         siblings = NULL;
+        hugepages = NULL;
     }
 
     ret = 0;
@@ -1868,6 +1906,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
     virBitmapFree(cpumap);
     VIR_FREE(cpus);
     VIR_FREE(siblings);
+    VIR_FREE(hugepages);
 
     if (ret < 0)
         VIR_FREE(cpus);
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 08c3d04..d07deeb 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -920,6 +920,29 @@ virQEMUCapsInitCPU(virCapsPtr caps,
 }
 
 
+static int
+virQEMUCapsInitHugePages(virCapsPtr caps)
+{
+    int ret = -1;
+    unsigned int *pages_size = NULL;
+    size_t npages;
+
+    if (virNumaGetHugePages(-1 /* Magic constant for overall info */,
+                            &pages_size, NULL, NULL, &npages) < 0)
+        goto cleanup;
+
+    caps->host.hugePagesSize = pages_size;
+    pages_size = NULL;
+    caps->host.nhugePagesSize = npages;
+    npages = 0;
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(pages_size);
+    return ret;
+}
+
+
 virCapsPtr virQEMUCapsInit(virQEMUCapsCachePtr cache)
 {
     virCapsPtr caps;
@@ -943,10 +966,14 @@ virCapsPtr virQEMUCapsInit(virQEMUCapsCachePtr cache)
         VIR_WARN("Failed to get host CPU");
 
     /* Add the power management features of the host */
-
     if (virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
         VIR_WARN("Failed to get host power management capabilities");
 
+    /* Add huge pages info */
+    if (virQEMUCapsInitHugePages(caps) < 0)
+        VIR_WARN("Failed to get huge pages info");
+
+    /* Add domain migration transport URI */
     virCapabilitiesAddHostMigrateTransport(caps,
                                            "tcp");
 
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index f9e2b3d..0bf710a 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -338,7 +338,7 @@ testBuildCapabilities(virConnectPtr conn)
 
         if (virCapabilitiesAddHostNUMACell(caps, i, 0,
                                            privconn->cells[i].numCpus,
-                                           cpu_cells, 0, NULL) < 0)
+                                           cpu_cells, 0, NULL, 0, NULL) < 0)
             goto error;
     }
 
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 5ddf71a..03fdde1 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1102,6 +1102,7 @@ sexpr_to_xend_topology(const struct sexpr *root, virCapsPtr caps)
 
         if (virCapabilitiesAddHostNUMACell(caps, cell, 0,
                                            nb_cpus, cpuInfo,
+                                           0, NULL,
                                            0, NULL) < 0)
             goto error;
         cpuInfo = NULL;
diff --git a/tests/vircaps2xmltest.c b/tests/vircaps2xmltest.c
index fa02534..7166c98 100644
--- a/tests/vircaps2xmltest.c
+++ b/tests/vircaps2xmltest.c
@@ -74,7 +74,8 @@ buildVirCapabilities(int max_cells,
         if (virCapabilitiesAddHostNUMACell(caps, cell_id,
                                            max_mem_in_cell,
                                            max_cpus_in_cell, cell_cpus,
-                                           nsiblings, siblings) < 0)
+                                           nsiblings, siblings,
+                                           0, NULL) < 0)
            goto error;
 
         cell_cpus = NULL;
diff --git a/tests/vircapstest.c b/tests/vircapstest.c
index 3edebba..59e9c2b 100644
--- a/tests/vircapstest.c
+++ b/tests/vircapstest.c
@@ -66,6 +66,7 @@ buildNUMATopology(int seq)
         if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq,
                                            MAX_MEM_IN_CELL,
                                            MAX_CPUS_IN_CELL, cell_cpus,
+                                           0, NULL,
                                            0, NULL) < 0)
            goto error;
 
-- 
1.8.5.5




More information about the libvir-list mailing list