diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng index d2d9776e49448bb836b17176fe31f36870e73e38..0c95c05d6851174b63c0d3991b2ab36a8c393865 100644 --- a/docs/schemas/capability.rng +++ b/docs/schemas/capability.rng @@ -188,6 +188,21 @@ + + + + + + + + + + + + + + + diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index cf474d72c6563acd2945de40d1330f4454c8a66d..408fab3f392c81347cc576475c233832a6977db6 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -107,6 +107,7 @@ virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell) virCapabilitiesClearHostNUMACellCPUTopology(cell->cpus, cell->ncpus); VIR_FREE(cell->cpus); + VIR_FREE(cell->siblings); VIR_FREE(cell); } @@ -275,9 +276,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, * virCapabilitiesAddHostNUMACell: * @caps: capabilities to extend * @num: ID number of NUMA cell - * @ncpus: number of CPUs in cell * @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 + * @nsiblings: number of sibling NUMA nodes + * @siblings: info on sibling NUMA nodes * * Registers a new NUMA cell for a host, passing in a * array of CPU IDs belonging to the cell @@ -285,9 +288,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, int virCapabilitiesAddHostNUMACell(virCapsPtr caps, int num, - int ncpus, unsigned long long mem, - virCapsHostNUMACellCPUPtr cpus) + int ncpus, + virCapsHostNUMACellCPUPtr cpus, + int nsiblings, + virCapsHostNUMACellSiblingInfoPtr siblings) { virCapsHostNUMACellPtr cell; @@ -302,6 +307,8 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, cell->num = num; cell->mem = mem; cell->cpus = cpus; + cell->siblings = siblings; + cell->nsiblings = nsiblings; caps->host.numaCell[caps->host.nnumaCell++] = cell; @@ -766,6 +773,18 @@ virCapabilitiesFormatNUMATopology(virBufferPtr buf, virBufferAsprintf(buf, "%llu\n", cells[i]->mem); + if (cells[i]->nsiblings) { + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + for (j = 0; j < cells[i]->nsiblings; j++) { + virBufferAsprintf(buf, "\n", + cells[i]->siblings[j].node, + cells[i]->siblings[j].distance); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } + virBufferAsprintf(buf, "\n", cells[i]->ncpus); virBufferAdjustIndent(buf, 2); for (j = 0; j < cells[i]->ncpus; j++) { diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index ba99e1a393c7d75f42c29e5c338c6c7a62234a15..53a83c9df740dd7600adf6c5dfc05225ca28ca56 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -95,6 +95,13 @@ struct _virCapsHostNUMACellCPU { 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 virCapsHostNUMACell *virCapsHostNUMACellPtr; struct _virCapsHostNUMACell { @@ -102,6 +109,8 @@ struct _virCapsHostNUMACell { int ncpus; unsigned long long mem; /* in kibibytes */ virCapsHostNUMACellCPUPtr cpus; + int nsiblings; + virCapsHostNUMACellSiblingInfoPtr siblings; }; typedef struct _virCapsHostSecModelLabel virCapsHostSecModelLabel; @@ -193,9 +202,11 @@ virCapabilitiesAddHostMigrateTransport(virCapsPtr caps, extern int virCapabilitiesAddHostNUMACell(virCapsPtr caps, int num, - int ncpus, unsigned long long mem, - virCapsHostNUMACellCPUPtr cpus); + int ncpus, + virCapsHostNUMACellCPUPtr cpus, + int nsiblings, + virCapsHostNUMACellSiblingInfoPtr siblings); extern int diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 14742decde2f3b376cd4b2ec662efbe9c6b1d853..cec37d6991b734fd6dacca82eab82e207ecb7d65 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -207,9 +207,10 @@ libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps) if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY) continue; - if (virCapabilitiesAddHostNUMACell(caps, i, nr_cpus_node[i], + if (virCapabilitiesAddHostNUMACell(caps, i, numa_info[i].size / 1024, - cpus[i]) < 0) { + nr_cpus_node[i], cpus[i], + 0, NULL) < 0) { virCapabilitiesClearHostNUMACellCPUTopology(cpus[i], nr_cpus_node[i]); goto cleanup; diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 56f2b02849b115fbf40cca0177c064afa4da7126..5eef42e20b2656acae0056e7600e2102a4ff9444 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -1644,9 +1644,9 @@ nodeCapsInitNUMAFake(virCapsPtr caps ATTRIBUTE_UNUSED) } if (virCapabilitiesAddHostNUMACell(caps, 0, - ncpus, nodeinfo.memory, - cpus) < 0) + ncpus, cpus, + 0, NULL) < 0) goto error; return 0; @@ -1748,6 +1748,53 @@ virNodeCapsFillCPUInfo(int cpu_id ATTRIBUTE_UNUSED, #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 nodeCapsInitNUMA(virCapsPtr caps) { @@ -1755,6 +1802,8 @@ nodeCapsInitNUMA(virCapsPtr caps) unsigned long long memory; virCapsHostNUMACellCPUPtr cpus = NULL; virBitmapPtr cpumap = NULL; + virCapsHostNUMACellSiblingInfoPtr siblings = NULL; + int nsiblings; int ret = -1; int ncpus = 0; 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 */ virNumaGetNodeMemory(n, &memory, NULL); memory >>= 10; - if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, memory, cpus) < 0) + if (virCapabilitiesAddHostNUMACell(caps, n, memory, + ncpus, cpus, + nsiblings, siblings) < 0) goto cleanup; cpus = NULL; + siblings = NULL; } ret = 0; @@ -1812,6 +1867,7 @@ nodeCapsInitNUMA(virCapsPtr caps) virBitmapFree(cpumap); VIR_FREE(cpus); + VIR_FREE(siblings); if (ret < 0) VIR_FREE(cpus); diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 37756e7ebcff73b7d34fb42de87726ba8acc9b0e..f9e2b3dcc83ed29d7f5342fbde1082364c997c16 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -336,8 +336,9 @@ testBuildCapabilities(virConnectPtr conn) sizeof(*cpu_cells) * privconn->cells[i].numCpus); - if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, - 0, cpu_cells) < 0) + if (virCapabilitiesAddHostNUMACell(caps, i, 0, + privconn->cells[i].numCpus, + cpu_cells, 0, NULL) < 0) goto error; } diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index c30b136ef22e643990658f5b96824e3b1d6c28e2..5ddf71acbc7aece405fb3fb4472f32e56ea5c34f 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1100,7 +1100,9 @@ sexpr_to_xend_topology(const struct sexpr *root, virCapsPtr caps) } virBitmapFree(cpuset); - if (virCapabilitiesAddHostNUMACell(caps, cell, nb_cpus, 0, cpuInfo) < 0) + if (virCapabilitiesAddHostNUMACell(caps, cell, 0, + nb_cpus, cpuInfo, + 0, NULL) < 0) goto error; cpuInfo = NULL; } diff --git a/tests/vircapstest.c b/tests/vircapstest.c index 821a92bc5818c4cf6a555515a5bb10141d2c2770..3edebba5ef13562c553ae82c5b0a3d630476913c 100644 --- a/tests/vircapstest.c +++ b/tests/vircapstest.c @@ -64,9 +64,9 @@ buildNUMATopology(int seq) id++; if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq, - MAX_CPUS_IN_CELL, MAX_MEM_IN_CELL, - cell_cpus) < 0) + MAX_CPUS_IN_CELL, cell_cpus, + 0, NULL) < 0) goto error; cell_cpus = NULL;