]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: add lscpu_read_numas()
authorKarel Zak <kzak@redhat.com>
Wed, 13 May 2020 11:33:36 +0000 (13:33 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Nov 2020 08:19:02 +0000 (09:19 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-api.h
sys-utils/lscpu-cputype.c

index aa686aa14a6a73b7ef79625ef34e00988bf8bfbf..6ea2df2e90fd7b68db0bb5dc21edd29eac72f300 100644 (file)
@@ -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);
index 2540b2b227b60df6da7e75c2a55d13f66225ad1f..9dcf7c741f9c7694b289d5bba28df6df7f32d705 100644 (file)
@@ -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;