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