---
docs/schemas/capability.rng | 10 ++++
src/conf/capabilities.c | 8 +++
src/conf/capabilities.h | 2 +
src/nodeinfo.c | 64 +++++++++++++++++++++-
src/test/test_driver.c | 2 +-
src/xen/xend_internal.c | 2 +-
tests/capabilityschemadata/caps-test3.xml | 88 +++++++++++++++++++++++++++++++
7 files changed, 173 insertions(+), 3 deletions(-)
create mode 100644 tests/capabilityschemadata/caps-test3.xml
diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
index 53fb04a..e0396aa 100644
--- a/docs/schemas/capability.rng
+++ b/docs/schemas/capability.rng
@@ -177,6 +177,10 @@
</attribute>
<optional>
+ <ref name='memory'/>
+ </optional>
+
+ <optional>
<element name='cpus'>
<attribute name='num'>
<ref name='unsignedInt'/>
@@ -189,6 +193,12 @@
</element>
</define>
+ <define name='memory'>
+ <element name='memory'>
+ <ref name='scaledInteger'/>
+ </element>
+ </define>
+
<define name='cpu'>
<element name='cpu'>
<attribute name='id'>
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index a0e597b..9824f0c 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -273,6 +273,7 @@ int
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
int num,
int ncpus,
+ unsigned long long mem,
virCapsHostNUMACellCPUPtr cpus)
{
virCapsHostNUMACellPtr cell;
@@ -286,6 +287,7 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
cell->ncpus = ncpus;
cell->num = num;
+ cell->mem = mem;
cell->cpus = cpus;
caps->host.numaCell[caps->host.nnumaCell++] = cell;
@@ -712,6 +714,12 @@ virCapabilitiesFormatNUMATopology(virBufferPtr xml,
virBufferAsprintf(xml, " <cells num='%zu'>\n", ncells);
for (i = 0; i < ncells; i++) {
virBufferAsprintf(xml, " <cell id='%d'>\n",
cells[i]->num);
+
+ /* Print out the numacell memory total if it is available */
+ if (cells[i]->mem)
+ virBufferAsprintf(xml, " <memory
unit='KiB'>%llu</memory>\n",
+ cells[i]->mem);
+
virBufferAsprintf(xml, " <cpus num='%d'>\n",
cells[i]->ncpus);
for (j = 0; j < cells[i]->ncpus; j++) {
virBufferAsprintf(xml, " <cpu id='%d'",
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index cc01765..6c67fb3 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -99,6 +99,7 @@ typedef virCapsHostNUMACell *virCapsHostNUMACellPtr;
struct _virCapsHostNUMACell {
int num;
int ncpus;
+ unsigned long long mem; /* in kibibytes */
virCapsHostNUMACellCPUPtr cpus;
};
@@ -210,6 +211,7 @@ extern int
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
int num,
int ncpus,
+ unsigned long long mem,
virCapsHostNUMACellCPUPtr cpus);
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 1622322..f9e173b 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -102,6 +102,7 @@ static int linuxNodeGetMemoryStats(FILE *meminfo,
int cellNum,
virNodeMemoryStatsPtr params,
int *nparams);
+static unsigned long long nodeGetCellMemory(int cell);
/* Return the positive decimal contents of the given
* DIR/cpu%u/FILE, or -1 on error. If DEFAULT_VALUE is non-negative
@@ -1531,6 +1532,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
int n;
unsigned long *mask = NULL;
unsigned long *allonesmask = NULL;
+ unsigned long long memory;
virCapsHostNUMACellCPUPtr cpus = NULL;
int ret = -1;
int max_n_cpus = NUMA_MAX_N_CPUS;
@@ -1562,6 +1564,11 @@ nodeCapsInitNUMA(virCapsPtr caps)
continue;
}
+ /* Detect the amount of memory in the numa cell */
+ memory = nodeGetCellMemory(n);
+ if (memory == 0)
+ goto cleanup;
+
for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++)
if (MASK_CPU_ISSET(mask, i))
ncpus++;
@@ -1578,7 +1585,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
}
}
- if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, cpus) < 0)
+ if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, memory, cpus) < 0)
goto cleanup;
}
@@ -1665,6 +1672,54 @@ cleanup:
return freeMem;
}
+/**
+ * nodeGetCellMemory
+ * @cell: The number of the numa cell to get memory info for.
+ *
+ * Will call the numa_node_size64() function from libnuma to get
+ * the amount of total memory in bytes. It is then converted to
+ * KiB and returned.
+ *
+ * Returns 0 on failure, amount of memory in KiB on success.
+ */
+static unsigned long long nodeGetCellMemory(int cell)
+{
+ long long mem;
+ unsigned long long memKiB = 0;
+ int maxCell;
+
+ if (numa_available() < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("NUMA not supported on this host"));
+ goto cleanup;
+ }
+
+ /* Make sure the provided cell number is valid. */
+ maxCell = numa_max_node();
+ if (cell > maxCell) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cell %d out of range (0-%d)"),
+ cell, maxCell);
+ goto cleanup;
+ }
+
+ /* Get the amount of memory(bytes) in the node */
+ mem = numa_node_size64(cell, NULL);
+ if (mem < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to query NUMA total memory for node: %d"),
+ cell);
+ goto cleanup;
+ }
+
+ /* Convert the memory from bytes to KiB */
+ memKiB = mem >> 10;
+
+cleanup:
+ return memKiB;
+}
+
+
#else
int nodeCapsInitNUMA(virCapsPtr caps ATTRIBUTE_UNUSED) {
return 0;
@@ -1686,4 +1741,11 @@ unsigned long long nodeGetFreeMemory(virConnectPtr conn
ATTRIBUTE_UNUSED)
_("NUMA memory information not available on this
platform"));
return 0;
}
+
+static unsigned long long nodeGetCellMemory(int cell)
+{
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("NUMA memory information not available on this
platform"));
+ return 0;
+}
#endif
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 30ce8e7..0037a6f 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -184,7 +184,7 @@ testBuildCapabilities(virConnectPtr conn) {
if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
- cpu_cells) < 0)
+ 0, cpu_cells) < 0)
goto no_memory;
}
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 27b87fc..4995d63 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -1141,7 +1141,7 @@ sexpr_to_xend_topology(const struct sexpr *root, virCapsPtr caps)
}
virBitmapFree(cpuset);
- if (virCapabilitiesAddHostNUMACell(caps, cell, nb_cpus, cpuInfo) < 0)
+ if (virCapabilitiesAddHostNUMACell(caps, cell, nb_cpus, 0, cpuInfo) < 0)
goto memory_error;
cpuInfo = NULL;
}
diff --git a/tests/capabilityschemadata/caps-test3.xml
b/tests/capabilityschemadata/caps-test3.xml
new file mode 100644
index 0000000..e6c56c5
--- /dev/null
+++ b/tests/capabilityschemadata/caps-test3.xml
@@ -0,0 +1,88 @@
+<capabilities>
+
+ <host>
+ <uuid>35383339-3134-5553-4531-30314e394a50</uuid>
+ <cpu>
+ <arch>x86_64</arch>
+ <model>Westmere</model>
+ <vendor>Intel</vendor>
+ <topology sockets='1' cores='6' threads='2'/>
+ <feature name='rdtscp'/>
+ <feature name='pdpe1gb'/>
+ <feature name='dca'/>
+ <feature name='pdcm'/>
+ <feature name='xtpr'/>
+ <feature name='tm2'/>
+ <feature name='est'/>
+ <feature name='smx'/>
+ <feature name='vmx'/>
+ <feature name='ds_cpl'/>
+ <feature name='monitor'/>
+ <feature name='dtes64'/>
+ <feature name='pclmuldq'/>
+ <feature name='pbe'/>
+ <feature name='tm'/>
+ <feature name='ht'/>
+ <feature name='ss'/>
+ <feature name='acpi'/>
+ <feature name='ds'/>
+ <feature name='vme'/>
+ </cpu>
+ <power_management>
+ <suspend_disk/>
+ </power_management>
+ <migration_features>
+ <live/>
+ <uri_transports>
+ <uri_transport>tcp</uri_transport>
+ </uri_transports>
+ </migration_features>
+ <topology>
+ <cells num='2'>
+ <cell id='0'>
+ <memory unit='KiB'>12572412</memory>
+ <cpus num='12'>
+ <cpu id='0'/>
+ <cpu id='2'/>
+ <cpu id='4'/>
+ <cpu id='6'/>
+ <cpu id='8'/>
+ <cpu id='10'/>
+ <cpu id='12'/>
+ <cpu id='14'/>
+ <cpu id='16'/>
+ <cpu id='18'/>
+ <cpu id='20'/>
+ <cpu id='22'/>
+ </cpus>
+ </cell>
+ <cell id='1'>
+ <memory unit='KiB'>12582908</memory>
+ <cpus num='12'>
+ <cpu id='1'/>
+ <cpu id='3'/>
+ <cpu id='5'/>
+ <cpu id='7'/>
+ <cpu id='9'/>
+ <cpu id='11'/>
+ <cpu id='13'/>
+ <cpu id='15'/>
+ <cpu id='17'/>
+ <cpu id='19'/>
+ <cpu id='21'/>
+ <cpu id='23'/>
+ </cpus>
+ </cell>
+ </cells>
+ </topology>
+ <secmodel>
+ <model>none</model>
+ <doi>0</doi>
+ </secmodel>
+ <secmodel>
+ <model>dac</model>
+ <doi>0</doi>
+ </secmodel>
+ </host>
+
+</capabilities>
--
1.7.11.7