mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
capabilities: Add additional data to the NUMA topology info
This patch adds data gathering to the NUMA gathering files and adds support for outputting the data. The test driver and xend driver need to be adapted to fill sensible data to the structure in a future patch.
This commit is contained in:
parent
87b4c10c6c
commit
79a003f9b0
@ -688,27 +688,47 @@ virCapabilitiesDefaultGuestEmulator(virCapsPtr caps,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
virCapabilitiesFormatNUMATopology(virBufferPtr xml,
|
virCapabilitiesFormatNUMATopology(virBufferPtr xml,
|
||||||
size_t ncells,
|
size_t ncells,
|
||||||
virCapsHostNUMACellPtr *cells)
|
virCapsHostNUMACellPtr *cells)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
char *siblings;
|
||||||
|
|
||||||
virBufferAddLit(xml, " <topology>\n");
|
virBufferAddLit(xml, " <topology>\n");
|
||||||
virBufferAsprintf(xml, " <cells num='%zu'>\n", ncells);
|
virBufferAsprintf(xml, " <cells num='%zu'>\n", ncells);
|
||||||
for (i = 0; i < ncells; i++) {
|
for (i = 0; i < ncells; i++) {
|
||||||
virBufferAsprintf(xml, " <cell id='%d'>\n", cells[i]->num);
|
virBufferAsprintf(xml, " <cell id='%d'>\n", cells[i]->num);
|
||||||
virBufferAsprintf(xml, " <cpus num='%d'>\n", cells[i]->ncpus);
|
virBufferAsprintf(xml, " <cpus num='%d'>\n", cells[i]->ncpus);
|
||||||
for (j = 0; j < cells[i]->ncpus; j++)
|
for (j = 0; j < cells[i]->ncpus; j++) {
|
||||||
virBufferAsprintf(xml, " <cpu id='%d'/>\n",
|
virBufferAsprintf(xml, " <cpu id='%d'",
|
||||||
cells[i]->cpus[j].id);
|
cells[i]->cpus[j].id);
|
||||||
|
|
||||||
|
if (cells[i]->cpus[j].siblings) {
|
||||||
|
if (!(siblings = virBitmapFormat(cells[i]->cpus[j].siblings))) {
|
||||||
|
virReportOOMError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(xml,
|
||||||
|
" socket_id='%d' core_id='%d' siblings='%s'",
|
||||||
|
cells[i]->cpus[j].socket_id,
|
||||||
|
cells[i]->cpus[j].core_id,
|
||||||
|
siblings);
|
||||||
|
VIR_FREE(siblings);
|
||||||
|
}
|
||||||
|
virBufferAddLit(xml, "/>\n");
|
||||||
|
}
|
||||||
|
|
||||||
virBufferAddLit(xml, " </cpus>\n");
|
virBufferAddLit(xml, " </cpus>\n");
|
||||||
virBufferAddLit(xml, " </cell>\n");
|
virBufferAddLit(xml, " </cell>\n");
|
||||||
}
|
}
|
||||||
virBufferAddLit(xml, " </cells>\n");
|
virBufferAddLit(xml, " </cells>\n");
|
||||||
virBufferAddLit(xml, " </topology>\n");
|
virBufferAddLit(xml, " </topology>\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -784,9 +804,10 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
|||||||
virBufferAddLit(&xml, " </migration_features>\n");
|
virBufferAddLit(&xml, " </migration_features>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps->host.nnumaCell)
|
if (caps->host.nnumaCell &&
|
||||||
virCapabilitiesFormatNUMATopology(&xml, caps->host.nnumaCell,
|
virCapabilitiesFormatNUMATopology(&xml, caps->host.nnumaCell,
|
||||||
caps->host.numaCell);
|
caps->host.numaCell) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < caps->host.nsecModels; i++) {
|
for (i = 0; i < caps->host.nsecModels; i++) {
|
||||||
virBufferAddLit(&xml, " <secmodel>\n");
|
virBufferAddLit(&xml, " <secmodel>\n");
|
||||||
|
@ -79,9 +79,11 @@ freebsdNodeGetCPUCount(void)
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# define CPUINFO_PATH "/proc/cpuinfo"
|
# define CPUINFO_PATH "/proc/cpuinfo"
|
||||||
# define SYSFS_SYSTEM_PATH "/sys/devices/system"
|
# define SYSFS_SYSTEM_PATH "/sys/devices/system"
|
||||||
|
# define SYSFS_CPU_PATH SYSFS_SYSTEM_PATH"/cpu"
|
||||||
# define PROCSTAT_PATH "/proc/stat"
|
# define PROCSTAT_PATH "/proc/stat"
|
||||||
# define MEMINFO_PATH "/proc/meminfo"
|
# define MEMINFO_PATH "/proc/meminfo"
|
||||||
# define SYSFS_MEMORY_SHARED_PATH "/sys/kernel/mm/ksm"
|
# define SYSFS_MEMORY_SHARED_PATH "/sys/kernel/mm/ksm"
|
||||||
|
# define SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX 1024
|
||||||
|
|
||||||
# define LINUX_NB_CPU_STATS 4
|
# define LINUX_NB_CPU_STATS 4
|
||||||
# define LINUX_NB_MEMORY_STATS_ALL 4
|
# define LINUX_NB_MEMORY_STATS_ALL 4
|
||||||
@ -1473,6 +1475,59 @@ cleanup:
|
|||||||
# define MASK_CPU_ISSET(mask, cpu) \
|
# define MASK_CPU_ISSET(mask, cpu) \
|
||||||
(((mask)[((cpu) / n_bits(*(mask)))] >> ((cpu) % n_bits(*(mask)))) & 1)
|
(((mask)[((cpu) / n_bits(*(mask)))] >> ((cpu) % n_bits(*(mask)))) & 1)
|
||||||
|
|
||||||
|
static virBitmapPtr
|
||||||
|
virNodeGetSiblingsList(const char *dir, int cpu_id)
|
||||||
|
{
|
||||||
|
char *path = NULL;
|
||||||
|
char *buf = NULL;
|
||||||
|
virBitmapPtr ret = NULL;
|
||||||
|
|
||||||
|
if (virAsprintf(&path, "%s/cpu%u/topology/thread_siblings_list",
|
||||||
|
dir, cpu_id) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileReadAll(path, SYSFS_THREAD_SIBLINGS_LIST_LENGTH_MAX, &buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virBitmapParse(buf, 0, &ret, NUMA_MAX_N_CPUS) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Failed to parse thread siblings"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(buf);
|
||||||
|
VIR_FREE(path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns 1 on success, 0 if the detection failed and -1 on hard error */
|
||||||
|
static int
|
||||||
|
virNodeCapsFillCPUInfo(int cpu_id, virCapsHostNUMACellCPUPtr cpu)
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
cpu->id = cpu_id;
|
||||||
|
|
||||||
|
if ((tmp = virNodeGetCpuValue(SYSFS_CPU_PATH, cpu_id,
|
||||||
|
"topology/physical_package_id", -1)) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cpu->socket_id = tmp;
|
||||||
|
|
||||||
|
if ((tmp = virNodeGetCpuValue(SYSFS_CPU_PATH, cpu_id,
|
||||||
|
"topology/core_id", -1)) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cpu->core_id = tmp;
|
||||||
|
|
||||||
|
if (!(cpu->siblings = virNodeGetSiblingsList(SYSFS_CPU_PATH, cpu_id)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nodeCapsInitNUMA(virCapsPtr caps)
|
nodeCapsInitNUMA(virCapsPtr caps)
|
||||||
{
|
{
|
||||||
@ -1483,6 +1538,7 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
int max_n_cpus = NUMA_MAX_N_CPUS;
|
int max_n_cpus = NUMA_MAX_N_CPUS;
|
||||||
int ncpus = 0;
|
int ncpus = 0;
|
||||||
|
bool topology_failed = false;
|
||||||
|
|
||||||
if (numa_available() < 0)
|
if (numa_available() < 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1516,20 +1572,28 @@ nodeCapsInitNUMA(virCapsPtr caps)
|
|||||||
if (VIR_ALLOC_N(cpus, ncpus) < 0)
|
if (VIR_ALLOC_N(cpus, ncpus) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++)
|
for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++) {
|
||||||
if (MASK_CPU_ISSET(mask, i))
|
if (MASK_CPU_ISSET(mask, i)) {
|
||||||
cpus[ncpus++].id = i;
|
if (virNodeCapsFillCPUInfo(i, cpus + ncpus++) < 0) {
|
||||||
|
topology_failed = true;
|
||||||
|
virResetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, cpus) < 0)
|
if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, cpus) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
cpus = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
if (topology_failed || ret < 0)
|
||||||
virCapabilitiesClearHostNUMACellCPUTopology(cpus, ncpus);
|
virCapabilitiesClearHostNUMACellCPUTopology(cpus, ncpus);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
VIR_FREE(cpus);
|
VIR_FREE(cpus);
|
||||||
|
|
||||||
VIR_FREE(mask);
|
VIR_FREE(mask);
|
||||||
VIR_FREE(allonesmask);
|
VIR_FREE(allonesmask);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user