0b5e55
diff -up util-linux-2.23.2/sys-utils/lscpu.c.kzak util-linux-2.23.2/sys-utils/lscpu.c
0b5e55
--- util-linux-2.23.2/sys-utils/lscpu.c.kzak	2013-07-30 10:39:26.342739583 +0200
0b5e55
+++ util-linux-2.23.2/sys-utils/lscpu.c	2014-01-14 11:21:51.837599200 +0100
0b5e55
@@ -49,6 +49,7 @@
0b5e55
 /* /sys paths */
0b5e55
 #define _PATH_SYS_SYSTEM	"/sys/devices/system"
0b5e55
 #define _PATH_SYS_CPU		_PATH_SYS_SYSTEM "/cpu"
0b5e55
+#define _PATH_SYS_NODE		_PATH_SYS_SYSTEM "/node"
0b5e55
 #define _PATH_PROC_XEN		"/proc/xen"
0b5e55
 #define _PATH_PROC_XENCAP	_PATH_PROC_XEN "/capabilities"
0b5e55
 #define _PATH_PROC_CPUINFO	"/proc/cpuinfo"
0b5e55
@@ -157,6 +158,7 @@ struct lscpu_desc {
0b5e55
 	cpu_set_t	*online;	/* mask with online CPUs */
0b5e55
 
0b5e55
 	int		nnodes;		/* number of NUMA modes */
0b5e55
+	int		*idx2nodenum;	/* Support for discontinuous nodes */
0b5e55
 	cpu_set_t	**nodemaps;	/* array with NUMA nodes */
0b5e55
 
0b5e55
 	/* books -- based on book_siblings (internal kernel map of cpuX's
0b5e55
@@ -802,25 +804,59 @@ read_cache(struct lscpu_desc *desc, int
0b5e55
 	}
0b5e55
 }
0b5e55
 
0b5e55
+static inline int is_node_dirent(struct dirent *d)
0b5e55
+{
0b5e55
+	return
0b5e55
+		d &&
0b5e55
+#ifdef _DIRENT_HAVE_D_TYPE
0b5e55
+		d->d_type == DT_DIR &&
0b5e55
+#endif
0b5e55
+		strncmp(d->d_name, "node", 4) == 0 &&
0b5e55
+		isdigit_string(d->d_name + 4);
0b5e55
+}
0b5e55
+
0b5e55
 static void
0b5e55
 read_nodes(struct lscpu_desc *desc)
0b5e55
 {
0b5e55
-	int i;
0b5e55
+	int i = 0;
0b5e55
+	DIR *dir;
0b5e55
+	struct dirent *d;
0b5e55
+	char *path;
0b5e55
 
0b5e55
 	/* number of NUMA node */
0b5e55
-	while (path_exist(_PATH_SYS_SYSTEM "/node/node%d", desc->nnodes))
0b5e55
-		desc->nnodes++;
0b5e55
+	path = path_strdup(_PATH_SYS_NODE);
0b5e55
+	dir = opendir(path);
0b5e55
+	free(path);
0b5e55
+
0b5e55
+	while (dir && (d = readdir(dir))) {
0b5e55
+		if (is_node_dirent(d))
0b5e55
+			desc->nnodes++;
0b5e55
+	}
0b5e55
 
0b5e55
-	if (!desc->nnodes)
0b5e55
+	if (!desc->nnodes) {
0b5e55
+		if (dir)
0b5e55
+			closedir(dir);
0b5e55
 		return;
0b5e55
+	}
0b5e55
 
0b5e55
 	desc->nodemaps = xcalloc(desc->nnodes, sizeof(cpu_set_t *));
0b5e55
+	desc->idx2nodenum = xmalloc(desc->nnodes * sizeof(int));
0b5e55
+
0b5e55
+	if (dir) {
0b5e55
+		rewinddir(dir);
0b5e55
+		while ((d = readdir(dir)) && i < desc->nnodes) {
0b5e55
+			if (is_node_dirent(d))
0b5e55
+				desc->idx2nodenum[i++] = strtol_or_err(((d->d_name) + 4),
0b5e55
+							_("Failed to extract the node number"));
0b5e55
+		}
0b5e55
+		closedir(dir);
0b5e55
+	}
0b5e55
 
0b5e55
 	/* information about how nodes share different CPUs */
0b5e55
 	for (i = 0; i < desc->nnodes; i++)
0b5e55
 		desc->nodemaps[i] = path_read_cpuset(maxcpus,
0b5e55
 					_PATH_SYS_SYSTEM "/node/node%d/cpumap",
0b5e55
-					i);
0b5e55
+					desc->idx2nodenum[i]);
0b5e55
 }
0b5e55
 
0b5e55
 static char *
0b5e55
@@ -850,7 +886,7 @@ get_cell_data(struct lscpu_desc *desc, i
0b5e55
 	case COL_NODE:
0b5e55
 		if (cpuset_ary_isset(cpu, desc->nodemaps,
0b5e55
 				     desc->nnodes, setsize, &idx) == 0)
0b5e55
-			snprintf(buf, bufsz, "%zd", idx);
0b5e55
+			snprintf(buf, bufsz, "%d", desc->idx2nodenum[idx]);
0b5e55
 		break;
0b5e55
 	case COL_BOOK:
0b5e55
 		if (cpuset_ary_isset(cpu, desc->bookmaps,
0b5e55
@@ -1250,7 +1286,7 @@ print_summary(struct lscpu_desc *desc, s
0b5e55
 	}
0b5e55
 
0b5e55
 	for (i = 0; i < desc->nnodes; i++) {
0b5e55
-		snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), i);
0b5e55
+		snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), desc->idx2nodenum[i]);
0b5e55
 		print_cpuset(buf, desc->nodemaps[i], mod->hex);
0b5e55
 	}
0b5e55
 }