--- docs/schemas/capability.rng | 5 ++ src/conf/capabilities.c | 38 +++++++++++-- src/conf/capabilities.h | 5 +- src/nodeinfo.c | 84 +++++++++++++++++++++++++++-- src/test/test_driver.c | 2 +- src/xen/xend_internal.c | 3 +- tests/capabilityschemadata/caps-test3.xml | 88 +++++++++++++++++++++++++++++++ 7 files changed, 216 insertions(+), 9 deletions(-) create mode 100644 tests/capabilityschemadata/caps-test3.xml diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng index 8c928bc..4147456 100644 --- a/docs/schemas/capability.rng +++ b/docs/schemas/capability.rng @@ -193,6 +193,11 @@ <attribute name='id'> <ref name='unsignedInt'/> </attribute> + <optional> + <attribute name='thread_siblings'> + <text/> + </attribute> + </optional> </element> </define> diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index a8ee2cf..08842bc 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -73,10 +73,16 @@ virCapabilitiesNew(const char *arch, static void virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell) { + int i; if (cell == NULL) return; + if (cell->threadSiblings) + for (i=0; i < cell->ncpus; i++) + VIR_FREE(cell->threadSiblings[i]); + VIR_FREE(cell->cpus); + VIR_FREE(cell->threadSiblings); VIR_FREE(cell); } @@ -253,7 +259,9 @@ int virCapabilitiesAddHostNUMACell(virCapsPtr caps, int num, int ncpus, - const int *cpus) + const int *cpus, + const virBitmapPtr *threadSiblings +) { virCapsHostNUMACellPtr cell; @@ -272,6 +280,16 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, cpus, ncpus * sizeof(*cpus)); + if (threadSiblings) { + if (VIR_ALLOC_N(cell->threadSiblings, ncpus) < 0) { + VIR_FREE(cell); + return -1; + } + memcpy(cell->threadSiblings, + threadSiblings, + ncpus * sizeof(*threadSiblings)); + } + cell->ncpus = ncpus; cell->num = num; @@ -695,6 +713,7 @@ virCapabilitiesFormatXML(virCapsPtr caps) virBuffer xml = VIR_BUFFER_INITIALIZER; int i, j, k; char host_uuid[VIR_UUID_STRING_BUFLEN]; + char *str; virBufferAddLit(&xml, "<capabilities>\n\n"); virBufferAddLit(&xml, " <host>\n"); @@ -762,9 +781,22 @@ virCapabilitiesFormatXML(virCapsPtr caps) caps->host.numaCell[i]->num); virBufferAsprintf(&xml, " <cpus num='%d'>\n", caps->host.numaCell[i]->ncpus); - for (j = 0 ; j < caps->host.numaCell[i]->ncpus ; j++) - virBufferAsprintf(&xml, " <cpu id='%d'/>\n", + for (j = 0 ; j < caps->host.numaCell[i]->ncpus ; j++) { + virBufferAsprintf(&xml, " <cpu id='%d'", caps->host.numaCell[i]->cpus[j]); + + /* Print out thread siblings if they were populated */ + if (caps->host.numaCell[i]->threadSiblings) { + str = virBitmapFormat(caps->host.numaCell[i]->threadSiblings[j]); + if (str) { + virBufferAsprintf(&xml, " thread_siblings='%s'", str); + VIR_FREE(str); + } + } + + virBufferAsprintf(&xml, "/>\n"); + } + virBufferAddLit(&xml, " </cpus>\n"); virBufferAddLit(&xml, " </cell>\n"); } diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 99056f8..5ef60c3 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -89,6 +89,7 @@ struct _virCapsHostNUMACell { int num; int ncpus; int *cpus; + virBitmapPtr *threadSiblings; }; typedef struct _virCapsHostSecModel virCapsHostSecModel; @@ -200,7 +201,9 @@ extern int virCapabilitiesAddHostNUMACell(virCapsPtr caps, int num, int ncpus, - const int *cpus); + const int *cpus, + const virBitmapPtr *threadSiblings +); extern int diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 8f96b8b..cb97ed5 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -56,6 +56,7 @@ #ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" # define SYSFS_SYSTEM_PATH "/sys/devices/system" +# define SYSFS_CPU_PATH "/sys/devices/system/cpu" # define PROCSTAT_PATH "/proc/stat" # define MEMINFO_PATH "/proc/meminfo" # define SYSFS_MEMORY_SHARED_PATH "/sys/kernel/mm/ksm" @@ -125,6 +126,58 @@ cleanup: return value; } +/** + * virNodeGetThreadSiblingsList + * @dir: directory where cpu0-N files are located. + * @cpu: the specific cpu to get the siblings for. + * + * Will open the "thread_siblings_list" file for the cpu and + * return a string representing the contents. The contents of the + * file is a string represnting the cpus that are siblings; like + * 1,9 or 1-4. + * + * Returns NULL on failure, char * on success + * + * Note: Responsibility of caller to free string + */ +static char *virNodeGetThreadSiblingsList(const char *dir, unsigned int cpu) +{ + char *path; + FILE *pathfp; + char *str; + int strsize = 1024; + + if (virAsprintf(&path, "%s/cpu%u/topology/thread_siblings_list", + dir, cpu) < 0) { + virReportOOMError(); + return NULL; + } + + pathfp = fopen(path, "r"); + if (pathfp == NULL) { + virReportSystemError(errno, _("cannot open %s"), path); + VIR_FREE(path); + return NULL; + } + + if (VIR_ALLOC_N(str, strsize) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (fgets(str, strsize, pathfp) == NULL) { + virReportSystemError(errno, _("cannot read from %s"), path); + VIR_FREE(str); + goto cleanup; + } + +cleanup: + VIR_FORCE_FCLOSE(pathfp); + VIR_FREE(path); + + return str; +} + static unsigned long virNodeCountThreadSiblings(const char *dir, unsigned int cpu) { @@ -1245,6 +1298,10 @@ nodeCapsInitNUMA(virCapsPtr caps) int *cpus = NULL; int ret = -1; int max_n_cpus = NUMA_MAX_N_CPUS; + char *str = NULL; + virBitmapPtr * threadSiblings = NULL; + + if (numa_available() < 0) return 0; @@ -1276,25 +1333,46 @@ nodeCapsInitNUMA(virCapsPtr caps) if (MASK_CPU_ISSET(mask, i)) ncpus++; + /* Create some memory for the array of cpus. */ if (VIR_ALLOC_N(cpus, ncpus) < 0) goto cleanup; - for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++) - if (MASK_CPU_ISSET(mask, i)) + /* Create some memory for the array of siblings. */ + if (VIR_ALLOC_N(threadSiblings, ncpus) < 0) + goto cleanup; + + for (ncpus = 0, i = 0 ; i < max_n_cpus ; i++) { + if (MASK_CPU_ISSET(mask, i)) { + + /* Get the string of thread siblings for this cpu */ + if (!(str = virNodeGetThreadSiblingsList(SYSFS_CPU_PATH, i))) + goto cleanup; + + /* Convert the string to a bitmap to be stored */ + if (virBitmapParse(str, 0, &threadSiblings[ncpus], max_n_cpus) < 0) + goto cleanup; + cpus[ncpus++] = i; + VIR_FREE(str); + } + } if (virCapabilitiesAddHostNUMACell(caps, n, ncpus, - cpus) < 0) + cpus, + threadSiblings) < 0) goto cleanup; + VIR_FREE(threadSiblings); VIR_FREE(cpus); } ret = 0; cleanup: + VIR_FREE(str); + VIR_FREE(threadSiblings); VIR_FREE(cpus); VIR_FREE(mask); VIR_FREE(allonesmask); diff --git a/src/test/test_driver.c b/src/test/test_driver.c index c9f9115..e3693ee 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -174,7 +174,7 @@ testBuildCapabilities(virConnectPtr conn) { for (i = 0; i < privconn->numCells; i++) { if (virCapabilitiesAddHostNUMACell(caps, i, privconn->cells[i].numCpus, - privconn->cells[i].cpus) < 0) + privconn->cells[i].cpus, NULL) < 0) goto no_memory; } diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 95152f8..3ee7cfa 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1167,7 +1167,8 @@ sexpr_to_xend_topology(const struct sexpr *root, if (virCapabilitiesAddHostNUMACell(caps, cell, nb_cpus, - cpuNums) < 0) + cpuNums, + NULL) < 0) goto memory_error; } VIR_FREE(cpuNums); diff --git a/tests/capabilityschemadata/caps-test3.xml b/tests/capabilityschemadata/caps-test3.xml new file mode 100644 index 0000000..eb90823 --- /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'> + <cpus num='12'> + <cpu id='0' thread_siblings='0,12'/> + <cpu id='2' thread_siblings='2,14'/> + <cpu id='4' thread_siblings='4,16'/> + <cpu id='6' thread_siblings='6,18'/> + <cpu id='8' thread_siblings='8,20'/> + <cpu id='10' thread_siblings='10,22'/> + <cpu id='12' thread_siblings='0,12'/> + <cpu id='14' thread_siblings='2,14'/> + <cpu id='16' thread_siblings='4,16'/> + <cpu id='18' thread_siblings='6,18'/> + <cpu id='20' thread_siblings='8,20'/> + <cpu id='22' thread_siblings='10,22'/> + </cpus> + </cell> + <cell id='1'> + <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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list