aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2020-05-13 13:33:36 +0200
committerKarel Zak <kzak@redhat.com>2020-11-13 09:19:02 +0100
commit154ee5a992b1a3b1dda25c1bd7ed296197e65bfd (patch)
tree4f460b22d4986874596c6f6c2f945ca6cf91aaf4
parent617d8fbec5a7075f3027108f368813a1eb231a1c (diff)
downloadutil-linux-154ee5a992b1a3b1dda25c1bd7ed296197e65bfd.tar.gz
lscpu: add lscpu_read_numas()
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--sys-utils/lscpu-api.h7
-rw-r--r--sys-utils/lscpu-cputype.c75
2 files changed, 81 insertions, 1 deletions
diff --git a/sys-utils/lscpu-api.h b/sys-utils/lscpu-api.h
index aa686aa14a..6ea2df2e90 100644
--- a/sys-utils/lscpu-api.h
+++ b/sys-utils/lscpu-api.h
@@ -124,7 +124,11 @@ struct lscpu_cxt {
struct lscpu_vulnerability *vuls; /* array of CPU vulnerabilities */
size_t nvuls; /* number of CPU vulnerabilities */
- unsigned int noalive;
+ size_t nnodes; /* number of NUMA modes */
+ int *idx2nodenum; /* Support for discontinuous nodes */
+ cpu_set_t **nodemaps; /* array with NUMA nodes */
+
+ unsigned int noalive : 1;
};
struct lscpu_cputype *lscpu_new_cputype(void);
@@ -138,6 +142,7 @@ int lscpu_read_architecture(struct lscpu_cxt *cxt);
int lscpu_read_cpulists(struct lscpu_cxt *cxt);
int lscpu_read_extra(struct lscpu_cxt *cxt);
int lscpu_read_vulnerabilities(struct lscpu_cxt *cxt);
+int lscpu_read_numas(struct lscpu_cxt *cxt);
struct lscpu_cpu *lscpu_new_cpu(void);
void lscpu_ref_cpu(struct lscpu_cpu *cpu);
diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c
index 2540b2b227..9dcf7c741f 100644
--- a/sys-utils/lscpu-cputype.c
+++ b/sys-utils/lscpu-cputype.c
@@ -667,6 +667,73 @@ int lscpu_read_vulnerabilities(struct lscpu_cxt *cxt)
return 0;
}
+static inline int is_node_dirent(struct dirent *d)
+{
+ return
+ d &&
+#ifdef _DIRENT_HAVE_D_TYPE
+ (d->d_type == DT_DIR || d->d_type == DT_UNKNOWN) &&
+#endif
+ strncmp(d->d_name, "node", 4) == 0 &&
+ isdigit_string(d->d_name + 4);
+}
+
+static int nodecmp(const void *ap, const void *bp)
+{
+ int *a = (int *) ap, *b = (int *) bp;
+ return *a - *b;
+}
+
+int lscpu_read_numas(struct lscpu_cxt *cxt)
+{
+ size_t i = 0;
+ DIR *dir;
+ struct dirent *d;
+ struct path_cxt *sys;
+
+ assert(!cxt->nnodes);
+
+ sys = ul_new_path(_PATH_SYS_NODE);
+ if (!sys)
+ err(EXIT_FAILURE, _("failed to initialize %s handler"), _PATH_SYS_NODE);
+
+ ul_path_set_prefix(sys, cxt->prefix);
+
+ dir = ul_path_opendir(sys, NULL);
+ if (!dir)
+ goto done;
+
+ while ((d = readdir(dir))) {
+ if (is_node_dirent(d))
+ cxt->nnodes++;
+ }
+
+ if (!cxt->nnodes) {
+ closedir(dir);
+ goto done;
+ }
+
+ cxt->nodemaps = xcalloc(cxt->nnodes, sizeof(cpu_set_t *));
+ cxt->idx2nodenum = xmalloc(cxt->nnodes * sizeof(int));
+
+ rewinddir(dir);
+ for (i = 0; (d = readdir(dir)) && i < cxt->nnodes; i++) {
+ if (is_node_dirent(d))
+ cxt->idx2nodenum[i] = strtol_or_err(((d->d_name) + 4),
+ _("Failed to extract the node number"));
+ }
+ closedir(dir);
+ qsort(cxt->idx2nodenum, cxt->nnodes, sizeof(int), nodecmp);
+
+ /* information about how nodes share different CPUs */
+ for (i = 0; i < cxt->nnodes; i++)
+ ul_path_readf_cpuset(sys, &cxt->nodemaps[i], cxt->maxcpus,
+ "node%d/cpumap", cxt->idx2nodenum[i]);
+done:
+ ul_unref_path(sys);
+ return 0;
+}
+
#ifdef TEST_PROGRAM_CPUTYPE
/* TODO: move to lscpu.c */
struct lscpu_cxt *lscpu_new_context(void)
@@ -709,6 +776,13 @@ void lscpu_free_context(struct lscpu_cxt *cxt)
free(cxt->vuls[i].text);
}
free(cxt->vuls);
+
+ for (i = 0; i < cxt->nnodes; i++)
+ free(cxt->nodemaps[i]);
+
+ free(cxt->nodemaps);
+ free(cxt->idx2nodenum);
+
free(cxt);
}
@@ -731,6 +805,7 @@ int main(int argc, char **argv)
lscpu_read_cpulists(cxt);
lscpu_read_extra(cxt);
lscpu_read_vulnerabilities(cxt);
+ lscpu_read_numas(cxt);
lscpu_free_context(cxt);
return EXIT_SUCCESS;