mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-08 12:41:29 +00:00
virCaps: Expose distance between host NUMA nodes
If user or management application wants to create a guest, it may be useful to know the cost of internode latencies before the guest resources are pinned. For example: <capabilities> <host> ... <topology> <cells num='2'> <cell id='0'> <memory unit='KiB'>4004132</memory> <distances> <sibling id='0' value='10'/> <sibling id='1' value='20'/> </distances> <cpus num='2'> <cpu id='0' socket_id='0' core_id='0' siblings='0'/> <cpu id='2' socket_id='0' core_id='2' siblings='2'/> </cpus> </cell> <cell id='1'> <memory unit='KiB'>4030064</memory> <distances> <sibling id='0' value='20'/> <sibling id='1' value='10'/> </distances> <cpus num='2'> <cpu id='1' socket_id='0' core_id='0' siblings='1'/> <cpu id='3' socket_id='0' core_id='2' siblings='3'/> </cpus> </cell> </cells> </topology> ... </host> ... </capabilities> We can see the distance from node1 to node0 is 20 and within nodes 10. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
77c830d8c4
commit
8ba0a58f8d
@ -188,6 +188,21 @@
|
|||||||
<ref name='memory'/>
|
<ref name='memory'/>
|
||||||
</optional>
|
</optional>
|
||||||
|
|
||||||
|
<optional>
|
||||||
|
<element name='distances'>
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name='sibling'>
|
||||||
|
<attribute name='id'>
|
||||||
|
<ref name='unsignedInt'/>
|
||||||
|
</attribute>
|
||||||
|
<attribute name='value'>
|
||||||
|
<ref name='unsignedInt'/>
|
||||||
|
</attribute>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
|
</element>
|
||||||
|
</optional>
|
||||||
|
|
||||||
<optional>
|
<optional>
|
||||||
<element name='cpus'>
|
<element name='cpus'>
|
||||||
<attribute name='num'>
|
<attribute name='num'>
|
||||||
|
@ -107,6 +107,7 @@ virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
|
|||||||
virCapabilitiesClearHostNUMACellCPUTopology(cell->cpus, cell->ncpus);
|
virCapabilitiesClearHostNUMACellCPUTopology(cell->cpus, cell->ncpus);
|
||||||
|
|
||||||
VIR_FREE(cell->cpus);
|
VIR_FREE(cell->cpus);
|
||||||
|
VIR_FREE(cell->siblings);
|
||||||
VIR_FREE(cell);
|
VIR_FREE(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,9 +276,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
|
|||||||
* virCapabilitiesAddHostNUMACell:
|
* virCapabilitiesAddHostNUMACell:
|
||||||
* @caps: capabilities to extend
|
* @caps: capabilities to extend
|
||||||
* @num: ID number of NUMA cell
|
* @num: ID number of NUMA cell
|
||||||
* @ncpus: number of CPUs in cell
|
|
||||||
* @mem: Total size of memory in the NUMA node (in KiB)
|
* @mem: Total size of memory in the NUMA node (in KiB)
|
||||||
|
* @ncpus: number of CPUs in cell
|
||||||
* @cpus: array of CPU definition structures, the pointer is stolen
|
* @cpus: array of CPU definition structures, the pointer is stolen
|
||||||
|
* @nsiblings: number of sibling NUMA nodes
|
||||||
|
* @siblings: info on sibling NUMA nodes
|
||||||
*
|
*
|
||||||
* Registers a new NUMA cell for a host, passing in a
|
* Registers a new NUMA cell for a host, passing in a
|
||||||
* array of CPU IDs belonging to the cell
|
* array of CPU IDs belonging to the cell
|
||||||
@ -285,9 +288,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
|
|||||||
int
|
int
|
||||||
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
||||||
int num,
|
int num,
|
||||||
int ncpus,
|
|
||||||
unsigned long long mem,
|
unsigned long long mem,
|
||||||
virCapsHostNUMACellCPUPtr cpus)
|
int ncpus,
|
||||||
|
virCapsHostNUMACellCPUPtr cpus,
|
||||||
|
int nsiblings,
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr siblings)
|
||||||
{
|
{
|
||||||
virCapsHostNUMACellPtr cell;
|
virCapsHostNUMACellPtr cell;
|
||||||
|
|
||||||
@ -302,6 +307,8 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
|||||||
cell->num = num;
|
cell->num = num;
|
||||||
cell->mem = mem;
|
cell->mem = mem;
|
||||||
cell->cpus = cpus;
|
cell->cpus = cpus;
|
||||||
|
cell->siblings = siblings;
|
||||||
|
cell->nsiblings = nsiblings;
|
||||||
|
|
||||||
caps->host.numaCell[caps->host.nnumaCell++] = cell;
|
caps->host.numaCell[caps->host.nnumaCell++] = cell;
|
||||||
|
|
||||||
@ -766,6 +773,18 @@ virCapabilitiesFormatNUMATopology(virBufferPtr buf,
|
|||||||
virBufferAsprintf(buf, "<memory unit='KiB'>%llu</memory>\n",
|
virBufferAsprintf(buf, "<memory unit='KiB'>%llu</memory>\n",
|
||||||
cells[i]->mem);
|
cells[i]->mem);
|
||||||
|
|
||||||
|
if (cells[i]->nsiblings) {
|
||||||
|
virBufferAddLit(buf, "<distances>\n");
|
||||||
|
virBufferAdjustIndent(buf, 2);
|
||||||
|
for (j = 0; j < cells[i]->nsiblings; j++) {
|
||||||
|
virBufferAsprintf(buf, "<sibling id='%d' value='%d'/>\n",
|
||||||
|
cells[i]->siblings[j].node,
|
||||||
|
cells[i]->siblings[j].distance);
|
||||||
|
}
|
||||||
|
virBufferAdjustIndent(buf, -2);
|
||||||
|
virBufferAddLit(buf, "</distances>\n");
|
||||||
|
}
|
||||||
|
|
||||||
virBufferAsprintf(buf, "<cpus num='%d'>\n", cells[i]->ncpus);
|
virBufferAsprintf(buf, "<cpus num='%d'>\n", cells[i]->ncpus);
|
||||||
virBufferAdjustIndent(buf, 2);
|
virBufferAdjustIndent(buf, 2);
|
||||||
for (j = 0; j < cells[i]->ncpus; j++) {
|
for (j = 0; j < cells[i]->ncpus; j++) {
|
||||||
|
@ -95,6 +95,13 @@ struct _virCapsHostNUMACellCPU {
|
|||||||
virBitmapPtr siblings;
|
virBitmapPtr siblings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virCapsHostNUMACellSiblingInfo virCapsHostNUMACellSiblingInfo;
|
||||||
|
typedef virCapsHostNUMACellSiblingInfo *virCapsHostNUMACellSiblingInfoPtr;
|
||||||
|
struct _virCapsHostNUMACellSiblingInfo {
|
||||||
|
int node; /* foreign NUMA node */
|
||||||
|
unsigned int distance; /* distance to the node */
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virCapsHostNUMACell virCapsHostNUMACell;
|
typedef struct _virCapsHostNUMACell virCapsHostNUMACell;
|
||||||
typedef virCapsHostNUMACell *virCapsHostNUMACellPtr;
|
typedef virCapsHostNUMACell *virCapsHostNUMACellPtr;
|
||||||
struct _virCapsHostNUMACell {
|
struct _virCapsHostNUMACell {
|
||||||
@ -102,6 +109,8 @@ struct _virCapsHostNUMACell {
|
|||||||
int ncpus;
|
int ncpus;
|
||||||
unsigned long long mem; /* in kibibytes */
|
unsigned long long mem; /* in kibibytes */
|
||||||
virCapsHostNUMACellCPUPtr cpus;
|
virCapsHostNUMACellCPUPtr cpus;
|
||||||
|
int nsiblings;
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr siblings;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel;
|
typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel;
|
||||||
@ -193,9 +202,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
|
|||||||
extern int
|
extern int
|
||||||
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
||||||
int num,
|
int num,
|
||||||
int ncpus,
|
|
||||||
unsigned long long mem,
|
unsigned long long mem,
|
||||||
virCapsHostNUMACellCPUPtr cpus);
|
int ncpus,
|
||||||
|
virCapsHostNUMACellCPUPtr cpus,
|
||||||
|
int nsiblings,
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr siblings);
|
||||||
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
|
@ -207,9 +207,10 @@ libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps)
|
|||||||
if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY)
|
if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, i, nr_cpus_node[i],
|
if (virCapabilitiesAddHostNUMACell(caps, i,
|
||||||
numa_info[i].size / 1024,
|
numa_info[i].size / 1024,
|
||||||
cpus[i]) < 0) {
|
nr_cpus_node[i], cpus[i],
|
||||||
|
0, NULL) < 0) {
|
||||||
virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
|
virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
|
||||||
nr_cpus_node[i]);
|
nr_cpus_node[i]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -1644,9 +1644,9 @@ nodeCapsInitNUMAFake(virCapsPtr caps ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, 0,
|
if (virCapabilitiesAddHostNUMACell(caps, 0,
|
||||||
ncpus,
|
|
||||||
nodeinfo.memory,
|
nodeinfo.memory,
|
||||||
cpus) < 0)
|
ncpus, cpus,
|
||||||
|
0, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1748,6 +1748,53 @@ virNodeCapsFillCPUInfo(int cpu_id ATTRIBUTE_UNUSED,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNodeCapsGetSiblingInfo(int node,
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr *siblings,
|
||||||
|
int *nsiblings)
|
||||||
|
{
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr tmp = NULL;
|
||||||
|
int tmp_size = 0;
|
||||||
|
int ret = -1;
|
||||||
|
int *distances = NULL;
|
||||||
|
int ndistances = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (virNumaGetDistances(node, &distances, &ndistances) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!distances) {
|
||||||
|
*siblings = NULL;
|
||||||
|
*nsiblings = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(tmp, ndistances) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < ndistances; i++) {
|
||||||
|
if (!distances[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tmp[tmp_size].node = i;
|
||||||
|
tmp[tmp_size].distance = distances[i];
|
||||||
|
tmp_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(tmp, tmp_size) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
*siblings = tmp;
|
||||||
|
*nsiblings = tmp_size;
|
||||||
|
tmp = NULL;
|
||||||
|
tmp_size = 0;
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(distances);
|
||||||
|
VIR_FREE(tmp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nodeCapsInitNUMA(virCapsPtr caps)
|
nodeCapsInitNUMA(virCapsPtr caps)
|
||||||
{
|
{
|
||||||
@ -1755,6 +1802,8 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
unsigned long long memory;
|
unsigned long long memory;
|
||||||
virCapsHostNUMACellCPUPtr cpus = NULL;
|
virCapsHostNUMACellCPUPtr cpus = NULL;
|
||||||
virBitmapPtr cpumap = NULL;
|
virBitmapPtr cpumap = NULL;
|
||||||
|
virCapsHostNUMACellSiblingInfoPtr siblings = NULL;
|
||||||
|
int nsiblings;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int ncpus = 0;
|
int ncpus = 0;
|
||||||
int cpu;
|
int cpu;
|
||||||
@ -1794,14 +1843,20 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virNodeCapsGetSiblingInfo(n, &siblings, &nsiblings) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* Detect the amount of memory in the numa cell in KiB */
|
/* Detect the amount of memory in the numa cell in KiB */
|
||||||
virNumaGetNodeMemory(n, &memory, NULL);
|
virNumaGetNodeMemory(n, &memory, NULL);
|
||||||
memory >>= 10;
|
memory >>= 10;
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, memory, cpus) < 0)
|
if (virCapabilitiesAddHostNUMACell(caps, n, memory,
|
||||||
|
ncpus, cpus,
|
||||||
|
nsiblings, siblings) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
cpus = NULL;
|
cpus = NULL;
|
||||||
|
siblings = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1812,6 +1867,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
|
|
||||||
virBitmapFree(cpumap);
|
virBitmapFree(cpumap);
|
||||||
VIR_FREE(cpus);
|
VIR_FREE(cpus);
|
||||||
|
VIR_FREE(siblings);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
VIR_FREE(cpus);
|
VIR_FREE(cpus);
|
||||||
|
@ -336,8 +336,9 @@ testBuildCapabilities(virConnectPtr conn)
|
|||||||
sizeof(*cpu_cells) * privconn->cells[i].numCpus);
|
sizeof(*cpu_cells) * privconn->cells[i].numCpus);
|
||||||
|
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus,
|
if (virCapabilitiesAddHostNUMACell(caps, i, 0,
|
||||||
0, cpu_cells) < 0)
|
privconn->cells[i].numCpus,
|
||||||
|
cpu_cells, 0, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1100,7 +1100,9 @@ sexpr_to_xend_topology(const struct sexpr *root, virCapsPtr caps)
|
|||||||
}
|
}
|
||||||
virBitmapFree(cpuset);
|
virBitmapFree(cpuset);
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, cell, nb_cpus, 0, cpuInfo) < 0)
|
if (virCapabilitiesAddHostNUMACell(caps, cell, 0,
|
||||||
|
nb_cpus, cpuInfo,
|
||||||
|
0, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
cpuInfo = NULL;
|
cpuInfo = NULL;
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ buildNUMATopology(int seq)
|
|||||||
id++;
|
id++;
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq,
|
if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq,
|
||||||
MAX_CPUS_IN_CELL,
|
|
||||||
MAX_MEM_IN_CELL,
|
MAX_MEM_IN_CELL,
|
||||||
cell_cpus) < 0)
|
MAX_CPUS_IN_CELL, cell_cpus,
|
||||||
|
0, NULL) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cell_cpus = NULL;
|
cell_cpus = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user