[libvirt] [RFC PATCH v2 1/4] PowerPC : Use Sysfs to gather host topology

Prerna Saxena prerna at linux.vnet.ibm.com
Mon Nov 14 14:46:30 UTC 2011


>From 9084802bdf7a2c10d6a913cb7dde001ab6ab3543 Mon Sep 17 00:00:00 2001
From: Prerna Saxena <prerna at linux.vnet.ibm.com>
Date: Mon, 3 Oct 2011 05:45:30 -0700
Subject: [PATCH 1/4] Use sysfs to gather host topology, in place of
 /proc/cpuinfo


Signed-off-by: Prerna Saxena <prerna at linux.vnet.ibm.com>
---
 src/nodeinfo.c |  106 +++++++++++++++++++-------------------------------------
 1 files changed, 36 insertions(+), 70 deletions(-)

diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 6448b79..cdd339d 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <dirent.h>
 #include <sys/utsname.h>
+#include <sched.h>
 
 #if HAVE_NUMACTL
 # define NUMA_VERSION1_COMPATIBILITY 1
@@ -191,6 +192,11 @@ static int parse_socket(unsigned int cpu)
     return ret;
 }
 
+static int parse_core(unsigned int cpu)
+{
+    return get_cpu_value(cpu, "topology/core_id", false);
+}
+
 int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                              virNodeInfoPtr nodeinfo,
                              bool need_hyperthreads)
@@ -199,15 +205,14 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
     DIR *cpudir = NULL;
     struct dirent *cpudirent = NULL;
     unsigned int cpu;
-    unsigned long cur_threads;
-    int socket;
-    unsigned long long socket_mask = 0;
-    unsigned int remaining;
+    unsigned long core, socket, cur_threads;
+    cpu_set_t core_mask;
+    cpu_set_t socket_mask;
     int online;
 
     nodeinfo->cpus = 0;
     nodeinfo->mhz = 0;
-    nodeinfo->cores = 1;
+    nodeinfo->cores = 0;
 
     nodeinfo->nodes = 1;
 # if HAVE_NUMACTL
@@ -221,20 +226,10 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
     /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */
     while (fgets(line, sizeof(line), cpuinfo) != NULL) {
         char *buf = line;
-        if (STRPREFIX(buf, "processor")) { /* aka a single logical CPU */
-            buf += 9;
-            while (*buf && c_isspace(*buf))
-                buf++;
-            if (*buf != ':') {
-                nodeReportError(VIR_ERR_INTERNAL_ERROR,
-                                "%s", _("parsing cpuinfo processor"));
-                return -1;
-            }
-            nodeinfo->cpus++;
 # if defined(__x86_64__) || \
     defined(__amd64__)  || \
     defined(__i386__)
-        } else if (STRPREFIX(buf, "cpu MHz")) {
+        if (STRPREFIX(buf, "cpu MHz")) {
             char *p;
             unsigned int ui;
             buf += 9;
@@ -249,24 +244,9 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                 /* Accept trailing fractional part.  */
                 && (*p == '\0' || *p == '.' || c_isspace(*p)))
                 nodeinfo->mhz = ui;
-        } else if (STRPREFIX(buf, "cpu cores")) { /* aka cores */
-            char *p;
-            unsigned int id;
-            buf += 9;
-            while (*buf && c_isspace(*buf))
-                buf++;
-            if (*buf != ':' || !buf[1]) {
-                nodeReportError(VIR_ERR_INTERNAL_ERROR,
-                                _("parsing cpuinfo cpu cores %c"), *buf);
-                return -1;
-            }
-            if (virStrToLong_ui(buf+1, &p, 10, &id) == 0
-                && (*p == '\0' || c_isspace(*p))
-                && id > nodeinfo->cores)
-                nodeinfo->cores = id;
 # elif defined(__powerpc__) || \
       defined(__powerpc64__)
-        } else if (STRPREFIX(buf, "clock")) {
+        if (STRPREFIX(buf, "clock")) {
             char *p;
             unsigned int ui;
             buf += 5;
@@ -281,53 +261,30 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                 /* Accept trailing fractional part.  */
                 && (*p == '\0' || *p == '.' || c_isspace(*p)))
                 nodeinfo->mhz = ui;
-# elif defined(__s390__) || \
-        defined(__s390x__)
-        } else if (STRPREFIX(buf, "# processors")) {
-            char *p;
-            unsigned int ui;
-            buf += 12;
-            while (*buf && c_isspace(*buf))
-                buf++;
-            if (*buf != ':' || !buf[1]) {
-                nodeReportError(VIR_ERR_INTERNAL_ERROR,
-                                _("parsing number of processors %c"), *buf);
-                return -1;
-            }
-            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
-                && (*p == '\0' || c_isspace(*p)))
-                nodeinfo->cpus = ui;
             /* No other interesting infos are available in /proc/cpuinfo.
              * However, there is a line identifying processor's version,
              * identification and machine, but we don't want it to be caught
              * and parsed in next iteration, because it is not in expected
              * format and thus lead to error. */
-            break;
 # else
 #  warning Parser for /proc/cpuinfo needs to be adapted for your architecture
 # endif
         }
     }
 
-    if (!nodeinfo->cpus) {
-        nodeReportError(VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("no cpus found"));
-        return -1;
-    }
-
-    if (!need_hyperthreads)
-        return 0;
-
-    /* OK, we've parsed what we can out of /proc/cpuinfo.  Get the socket
-     * and thread information from /sys
+    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the core, socket
+     * thread and topology information from /sys
      */
-    remaining = nodeinfo->cpus;
     cpudir = opendir(CPU_SYS_PATH);
     if (cpudir == NULL) {
         virReportSystemError(errno, _("cannot opendir %s"), CPU_SYS_PATH);
         return -1;
     }
-    while ((errno = 0), remaining && (cpudirent = readdir(cpudir))) {
+
+    CPU_ZERO(&core_mask);
+    CPU_ZERO(&socket_mask);
+
+    while (cpudirent = readdir(cpudir)) {
         if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
             continue;
 
@@ -338,15 +295,19 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
         }
         if (!online)
             continue;
-        remaining--;
+        nodeinfo->cpus++;
 
-        socket = parse_socket(cpu);
-        if (socket < 0) {
-            closedir(cpudir);
-            return -1;
+        /* Parse core */
+        core = parse_core(cpu);
+        if (!CPU_ISSET(core, &core_mask)) {
+            CPU_SET(core, &core_mask);
+            nodeinfo->cores++;
         }
-        if (!(socket_mask & (1 << socket))) {
-            socket_mask |= (1 << socket);
+
+        /* Parse socket */
+        socket = parse_socket(cpu);
+        if (!CPU_ISSET(socket, &socket_mask)) {
+            CPU_SET(socket, &socket_mask);
             nodeinfo->sockets++;
         }
 
@@ -367,7 +328,12 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
 
     closedir(cpudir);
 
-    /* there should always be at least one socket and one thread */
+    /* there should always be at least one cpu, socket and one thread */
+    if (nodeinfo->cpus == 0) {
+        nodeReportError(VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("no CPUs found"));
+        return -1;
+    }
     if (nodeinfo->sockets == 0) {
         nodeReportError(VIR_ERR_INTERNAL_ERROR,
                         "%s", _("no sockets found"));
-- 
1.7.7



-- 
Prerna Saxena

Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India





More information about the libvir-list mailing list