[libvirt] [PATCH] Add cpu thread siblings information to virsh capabilities.

Dusty Mabe dustymabe at gmail.com
Tue Oct 23 23:19:07 UTC 2012


---
 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




More information about the libvir-list mailing list