Skip to contentSkip to conversation

perf tools: Assorted fixes

PATCH Superseded Jiri Olsa 3 participants 6 messages Feb 18, 2019 perf events

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Jiri Olsa

author reviewer
#0 lore raw

v2 cover perf tools: Assorted fixes

hi,
sending assorted general fixes that queued
up in my other branches.

v2 changes:
- renamed the interface to struct cpu_topology/numa_topology plus related changes in function names
- adding missing Fixes tag

Also available in here:
https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/fixes

thanks,
jirka

---
Jiri Olsa (3):
perf header: Fix wrong node write in NUMA_TOPOLOGY feature perf tools: Add cpu_topology object
perf tools: Add numa_topology object

 tools/perf/util/Build     |   1 +
 tools/perf/util/cputopo.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cputopo.h |  33 ++++++++++++++++++++++
 tools/perf/util/header.c  | 269 ++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------
 4 files changed, 328 insertions(+), 239 deletions(-)
 create mode 100644 tools/perf/util/cputopo.c
 create mode 100644 tools/perf/util/cputopo.h
author reviewer
#1 lore raw

PATCH v2 1/3 perf header: Fix wrong node write in NUMA_TOPOLOGY feature

We are currently passing the node index instead of the real node number.

Fixes fbe96f29ce4b ("perf tools: Make perf.data more self-descriptive (v8)"
---
 tools/perf/util/header.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/header.c +1 -1
index 61ce197c5362..c66f26ec557a 100644
@@ -879,7 +879,7 @@ static int write_numa_topology(struct feat_fd *ff,
 		if (ret < 0)
 			break;
 
-		ret = write_topo_node(ff, i);
+		ret = write_topo_node(ff, j);
 		if (ret < 0)
 			break;
 	}
Signature · 1 line
2.17.2
author reviewer
#2 lore raw

PATCH v2 2/3 perf tools: Add cpu_topology object

In reply to Jiri Olsa

Making struct cpu_topo global and renaming it to struct cpu_topology, so it can be used from record command in following patches.

Adding following interface functions to load/free cpu topology details:
struct cpu_topology *cpu_topology__new(void); void cpu_topology__delete(struct cpu_topology *tp);

Moving it into separate object file cputopo.c together with numa related object in following patches.

No functional change, the new interface will be used in upcoming changes.

---
 tools/perf/util/Build     |   1 +
 tools/perf/util/cputopo.c | 144 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/cputopo.h |  17 +++++
 tools/perf/util/header.c  | 150 +-------------------------------------
 4 files changed, 166 insertions(+), 146 deletions(-)
 create mode 100644 tools/perf/util/cputopo.c
 create mode 100644 tools/perf/util/cputopo.h
tools/perf/util/Build +1 -0
index ca0741c91903..3008d49fa587 100644
@@ -69,6 +69,7 @@ perf-y += hist.o
 perf-y += util.o
 perf-y += xyarray.o
 perf-y += cpumap.o
+perf-y += cputopo.o
 perf-y += cgroup.o
 perf-y += target.o
 perf-y += rblist.o
tools/perf/util/cputopo.c new file +144 -0

144 lines not on this page · raw message

tools/perf/util/cputopo.h new file +17 -0
new file mode 100644
index 000000000000..4b5f4112b6f8
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_CPUTOPO_H
+#define __PERF_CPUTOPO_H
+
+#include <linux/types.h>
+
+struct cpu_topology {
+	u32	  core_sib;
+	u32	  thread_sib;
+	char	**core_siblings;
+	char	**thread_siblings;
+};
+
+struct cpu_topology *cpu_topology__new(void);
+void cpu_topology__delete(struct cpu_topology *tp);
+
+#endif /* __PERF_CPUTOPO_H */
tools/perf/util/header.c +4 -146

175 lines not on this page · raw message

Signature · 1 line
2.17.2
author reviewer
#3 lore raw

PATCH v2 3/3 perf tools: Add numa_topology object

In reply to Jiri Olsa

Adding numa_topology object to return the list of numa nodes together with their cpus. It will replace the numa code in header.c and will be used from perf record code in following patches.

Adding following interface functions to load numa details:

  struct numa_topology *numa_topology__new(void);
  void numa_topology__delete(struct numa_topology *tp);

And replacing current (copied) local interface, with no functional changes.

---
 tools/perf/util/cputopo.c | 120 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cputopo.h |  16 +++++
 tools/perf/util/header.c  | 119 +++++++++----------------------------
 3 files changed, 162 insertions(+), 93 deletions(-)
tools/perf/util/cputopo.c +120 -0
index 84470ed4e707..daac3cf90b12 100644
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/param.h>
+#include <inttypes.h>
 
 #include "cputopo.h"
 #include "cpumap.h"
 #include "util.h"
+#include "env.h"
 
 
 #define CORE_SIB_FMT \
@@ -142,3 +144,121 @@ struct cpu_topology *cpu_topology__new(void)
 	}
 	return tp;
 }
+
+static int load_numa_node(struct numa_topology_node *node, int nr)
+{
+	char str[MAXPATHLEN];
+	char field[32];
+	char *buf = NULL, *p;
+	size_t len = 0;
+	int ret = -1;
+	FILE *fp;
+	u64 mem;
+
+	node->node = (u32) nr;
+
+	sprintf(str, "/sys/devices/system/node/node%d/meminfo", nr);
+	fp = fopen(str, "r");
+	if (!fp)
+		return -1;
+
+	while (getline(&buf, &len, fp) > 0) {
+		/* skip over invalid lines */
+		if (!strchr(buf, ':'))
+			continue;
+		if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
+			goto err;
+		if (!strcmp(field, "MemTotal:"))
+			node->mem_total = mem;
+		if (!strcmp(field, "MemFree:"))
+			node->mem_free = mem;
+		if (node->mem_total && node->mem_free)
+			break;
+	}
+
+	fclose(fp);
+	fp  = NULL;
+	buf = NULL;
+
+	ret = -1;
+	sprintf(str, "/sys/devices/system/node/node%d/cpulist", nr);
+
+	fp = fopen(str, "r");
+	if (!fp)
+		return -1;
+
+	if (getline(&buf, &len, fp) <= 0)
+		goto err;
+
+	p = strchr(buf, '\n');
+	if (p)
+		*p = '\0';
+
+	node->cpus = buf;
+	fclose(fp);
+	return 0;
+
+err:
+	free(buf);
+	if (fp)
+		fclose(fp);
+	return ret;
+}
+
+struct numa_topology *numa_topology__new(void)
+{
+	struct cpu_map *node_map = NULL;
+	struct numa_topology *tp = NULL;
+	char *buf = NULL;
+	size_t len = 0;
+	u32 nr, i;
+	FILE *fp;
+	char *c;
+
+	fp = fopen("/sys/devices/system/node/online", "r");
+	if (!fp)
+		return NULL;
+
+	if (getline(&buf, &len, fp) <= 0)
+		goto out;
+
+	c = strchr(buf, '\n');
+	if (c)
+		*c = '\0';
+
+	node_map = cpu_map__new(buf);
+	if (!node_map)
+		goto out;
+
+	nr = (u32) node_map->nr;
+
+	tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
+	if (!tp)
+		goto out;
+
+	tp->nr = nr;
+
+	for (i = 0; i < nr; i++) {
+		if (load_numa_node(&tp->nodes[i], node_map->map[i])) {
+			numa_topology__delete(tp);
+			tp = NULL;
+			break;
+		}
+	}
+
+out:
+	free(buf);
+	fclose(fp);
+	cpu_map__put(node_map);
+	return tp;
+}
+
+void numa_topology__delete(struct numa_topology *tp)
+{
+	u32 i;
+
+	for (i = 0; i < tp->nr; i++)
+		free(tp->nodes[i].cpus);
+
+	free(tp);
+}
tools/perf/util/cputopo.h +16 -0
index 4b5f4112b6f8..47a97e71acdf 100644
@@ -3,6 +3,7 @@
 #define __PERF_CPUTOPO_H
 
 #include <linux/types.h>
+#include "env.h"
 
 struct cpu_topology {
 	u32	  core_sib;
@@ -11,7 +12,22 @@ struct cpu_topology {
 	char	**thread_siblings;
 };
 
+struct numa_topology_node {
+	char		*cpus;
+	u32		 node;
+	u64		 mem_total;
+	u64		 mem_free;
+};
+
+struct numa_topology {
+	u32				nr;
+	struct numa_topology_node	nodes[0];
+};
+
 struct cpu_topology *cpu_topology__new(void);
 void cpu_topology__delete(struct cpu_topology *tp);
 
+struct numa_topology *numa_topology__new(void);
+void numa_topology__delete(struct numa_topology *tp);
+
 #endif /* __PERF_CPUTOPO_H */
tools/perf/util/header.c +26 -93

138 lines not on this page · raw message

Signature · 1 line
2.17.2
maintainer
#4 lore raw

Re: [PATCH 3/3] perf tools: Add numa_topology object

Hi Jirka,

Quoted 46 lines · Jiri Olsa

Adding numa_topology object to return the list of numa nodes together with their cpus. It will replace the numa code in header.c and will be used from perf record code in following patches.

Adding following interface functions to load numa details:

  struct numa_topology *numa_topology__new(void);
  void numa_topology__delete(struct numa_topology *tp);

And replacing current (copied) local interface, with no functional changes.

---
 tools/perf/util/cputopo.c | 120 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cputopo.h |  16 +++++
 tools/perf/util/header.c  | 119 +++++++++----------------------------
 3 files changed, 162 insertions(+), 93 deletions(-)
tools/perf/util/cputopo.c +6 -0
index 84470ed4e707..daac3cf90b12 100644
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/param.h>
+#include <inttypes.h>
 
 #include "cputopo.h"
 #include "cpumap.h"
 #include "util.h"
+#include "env.h"
 
 
 #define CORE_SIB_FMT \
@@ -142,3 +144,121 @@ struct cpu_topology *cpu_topology__new(void)
        }
        return tp;
 }
+
+static int load_numa_node(struct numa_topology_node *node, int nr)
+{
+       char str[MAXPATHLEN];

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 160

Quoted 10 lines
tools/perf/util/cputopo.c +10 -0
+       char field[32];
+       char *buf = NULL, *p;
+       size_t len = 0;
+       int ret = -1;
+       FILE *fp;
+       u64 mem;
+
+       node->node = (u32) nr;
+
+       sprintf(str, "/sys/devices/system/node/node%d/meminfo", nr);

Why not using similar macro like NODE_MEMINFO_FMT? Also it'd be better using snprintf() or scnprintf() instead.

Quoted 11 lines
tools/perf/util/cputopo.c +11 -0
+       fp = fopen(str, "r");
+       if (!fp)
+               return -1;
+
+       while (getline(&buf, &len, fp) > 0) {
+               /* skip over invalid lines */
+               if (!strchr(buf, ':'))
+                       continue;
+               if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
+                       goto err;
+               if (!strcmp(field, "MemTotal:"))

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 181

Quoted 10 lines
tools/perf/util/cputopo.c +10 -0
+                       node->mem_total = mem;
+               if (!strcmp(field, "MemFree:"))
+                       node->mem_free = mem;
+               if (node->mem_total && node->mem_free)
+                       break;
+       }
+
+       fclose(fp);
+       fp  = NULL;
+       buf = NULL;

No need to make them NULL. Also it'd leak buf..

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 183

Quoted 2 lines
tools/perf/util/cputopo.c +2 -0
+
+       ret = -1;

It's not changed yet.

Thanks,
Namhyung

Quoted 262 lines
tools/perf/util/cputopo.c +81 -0
+       sprintf(str, "/sys/devices/system/node/node%d/cpulist", nr);
+
+       fp = fopen(str, "r");
+       if (!fp)
+               return -1;
+
+       if (getline(&buf, &len, fp) <= 0)
+               goto err;
+
+       p = strchr(buf, '\n');
+       if (p)
+               *p = '\0';
+
+       node->cpus = buf;
+       fclose(fp);
+       return 0;
+
+err:
+       free(buf);
+       if (fp)
+               fclose(fp);
+       return ret;
+}
+
+struct numa_topology *numa_topology__new(void)
+{
+       struct cpu_map *node_map = NULL;
+       struct numa_topology *tp = NULL;
+       char *buf = NULL;
+       size_t len = 0;
+       u32 nr, i;
+       FILE *fp;
+       char *c;
+
+       fp = fopen("/sys/devices/system/node/online", "r");
+       if (!fp)
+               return NULL;
+
+       if (getline(&buf, &len, fp) <= 0)
+               goto out;
+
+       c = strchr(buf, '\n');
+       if (c)
+               *c = '\0';
+
+       node_map = cpu_map__new(buf);
+       if (!node_map)
+               goto out;
+
+       nr = (u32) node_map->nr;
+
+       tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
+       if (!tp)
+               goto out;
+
+       tp->nr = nr;
+
+       for (i = 0; i < nr; i++) {
+               if (load_numa_node(&tp->nodes[i], node_map->map[i])) {
+                       numa_topology__delete(tp);
+                       tp = NULL;
+                       break;
+               }
+       }
+
+out:
+       free(buf);
+       fclose(fp);
+       cpu_map__put(node_map);
+       return tp;
+}
+
+void numa_topology__delete(struct numa_topology *tp)
+{
+       u32 i;
+
+       for (i = 0; i < tp->nr; i++)
+               free(tp->nodes[i].cpus);
+
+       free(tp);
+}
tools/perf/util/cputopo.h +16 -0
index 4b5f4112b6f8..47a97e71acdf 100644
@@ -3,6 +3,7 @@
 #define __PERF_CPUTOPO_H
 
 #include <linux/types.h>
+#include "env.h"
 
 struct cpu_topology {
        u32       core_sib;
@@ -11,7 +12,22 @@ struct cpu_topology {
        char    **thread_siblings;
 };
 
+struct numa_topology_node {
+       char            *cpus;
+       u32              node;
+       u64              mem_total;
+       u64              mem_free;
+};
+
+struct numa_topology {
+       u32                             nr;
+       struct numa_topology_node       nodes[0];
+};
+
 struct cpu_topology *cpu_topology__new(void);
 void cpu_topology__delete(struct cpu_topology *tp);
 
+struct numa_topology *numa_topology__new(void);
+void numa_topology__delete(struct numa_topology *tp);
+
 #endif /* __PERF_CPUTOPO_H */
tools/perf/util/header.c +26 -94
index 80ac57e6d38f..a2323d777dae 100644
@@ -639,112 +639,45 @@ static int write_total_mem(struct feat_fd *ff,
        return ret;
 }
 
-static int write_topo_node(struct feat_fd *ff, int node)
-{
-       char str[MAXPATHLEN];
-       char field[32];
-       char *buf = NULL, *p;
-       size_t len = 0;
-       FILE *fp;
-       u64 mem_total, mem_free, mem;
-       int ret = -1;
-
-       sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
-       fp = fopen(str, "r");
-       if (!fp)
-               return -1;
-
-       while (getline(&buf, &len, fp) > 0) {
-               /* skip over invalid lines */
-               if (!strchr(buf, ':'))
-                       continue;
-               if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
-                       goto done;
-               if (!strcmp(field, "MemTotal:"))
-                       mem_total = mem;
-               if (!strcmp(field, "MemFree:"))
-                       mem_free = mem;
-       }
-
-       fclose(fp);
-       fp = NULL;
-
-       ret = do_write(ff, &mem_total, sizeof(u64));
-       if (ret)
-               goto done;
-
-       ret = do_write(ff, &mem_free, sizeof(u64));
-       if (ret)
-               goto done;
-
-       ret = -1;
-       sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
-
-       fp = fopen(str, "r");
-       if (!fp)
-               goto done;
-
-       if (getline(&buf, &len, fp) <= 0)
-               goto done;
-
-       p = strchr(buf, '\n');
-       if (p)
-               *p = '\0';
-
-       ret = do_write_string(ff, buf);
-done:
-       free(buf);
-       if (fp)
-               fclose(fp);
-       return ret;
-}
-
 static int write_numa_topology(struct feat_fd *ff,
                               struct perf_evlist *evlist __maybe_unused)
 {
-       char *buf = NULL;
-       size_t len = 0;
-       FILE *fp;
-       struct cpu_map *node_map = NULL;
-       char *c;
-       u32 nr, i, j;
+       struct numa_topology *tp;
        int ret = -1;
+       u32 i;
 
-       fp = fopen("/sys/devices/system/node/online", "r");
-       if (!fp)
-               return -1;
+       tp = numa_topology__new();
+       if (!tp)
+               return -ENOMEM;
 
-       if (getline(&buf, &len, fp) <= 0)
-               goto done;
+       ret = do_write(ff, &tp->nr, sizeof(u32));
+       if (ret < 0)
+               goto err;
 
-       c = strchr(buf, '\n');
-       if (c)
-               *c = '\0';
+       for (i = 0; i < tp->nr; i++) {
+               struct numa_topology_node *n = &tp->nodes[i];
 
-       node_map = cpu_map__new(buf);
-       if (!node_map)
-               goto done;
-
-       nr = (u32)node_map->nr;
+               ret = do_write(ff, &n->node, sizeof(u32));
+               if (ret < 0)
+                       goto err;
 
-       ret = do_write(ff, &nr, sizeof(nr));
-       if (ret < 0)
-               goto done;
+               ret = do_write(ff, &n->mem_total, sizeof(u64));
+               if (ret)
+                       goto err;
 
-       for (i = 0; i < nr; i++) {
-               j = (u32)node_map->map[i];
-               ret = do_write(ff, &j, sizeof(j));
-               if (ret < 0)
-                       break;
+               ret = do_write(ff, &n->mem_free, sizeof(u64));
+               if (ret)
+                       goto err;
 
-               ret = write_topo_node(ff, j);
+               ret = do_write_string(ff, n->cpus);
                if (ret < 0)
-                       break;
+                       goto err;
        }
-done:
-       free(buf);
-       fclose(fp);
-       cpu_map__put(node_map);
+
+       ret = 0;
+
+err:
+       numa_topology__delete(tp);
        return ret;
 }
 
--

2.17.2

Signature · 2 lines
Thanks,
Namhyung
#5 lore raw

Re: [PATCH 3/3] perf tools: Add numa_topology object

Quoted 54 lines · Namhyung Kim

Hi Jirka,

Quoted 51 lines · Jiri Olsa

Adding numa_topology object to return the list of numa nodes together with their cpus. It will replace the numa code in header.c and will be used from perf record code in following patches.

Adding following interface functions to load numa details:

  struct numa_topology *numa_topology__new(void);
  void numa_topology__delete(struct numa_topology *tp);

And replacing current (copied) local interface, with no functional changes.

---
 tools/perf/util/cputopo.c | 120 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cputopo.h |  16 +++++
 tools/perf/util/header.c  | 119 +++++++++----------------------------
 3 files changed, 162 insertions(+), 93 deletions(-)
tools/perf/util/cputopo.c +11 -0
index 84470ed4e707..daac3cf90b12 100644
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/param.h>
+#include <inttypes.h>
 
 #include "cputopo.h"
 #include "cpumap.h"
 #include "util.h"
+#include "env.h"
 
 
 #define CORE_SIB_FMT \
@@ -142,3 +144,121 @@ struct cpu_topology *cpu_topology__new(void)
        }
        return tp;
 }
+
+static int load_numa_node(struct numa_topology_node *node, int nr)
+{
+       char str[MAXPATHLEN];
+       char field[32];
+       char *buf = NULL, *p;
+       size_t len = 0;
+       int ret = -1;
+       FILE *fp;
Quoted 8 lines

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 160

Quoted 5 lines
tools/perf/util/cputopo.c +5 -0
+       u64 mem;
+
+       node->node = (u32) nr;
+
+       sprintf(str, "/sys/devices/system/node/node%d/meminfo", nr);

Why not using similar macro like NODE_MEMINFO_FMT? Also it'd be better using snprintf() or scnprintf() instead.

right, that code needs to be changed to take /sys from sysfs__mountpoint

but I wanted just to move the code now, with only necessary changes, like the issues you found below ;-)

Quoted 17 lines
Quoted 17 lines
tools/perf/util/cputopo.c +15 -0
+       fp = fopen(str, "r");
+       if (!fp)
+               return -1;
+
+       while (getline(&buf, &len, fp) > 0) {
+               /* skip over invalid lines */
+               if (!strchr(buf, ':'))
+                       continue;
+               if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
+                       goto err;
+               if (!strcmp(field, "MemTotal:"))
+                       node->mem_total = mem;
+               if (!strcmp(field, "MemFree:"))
+                       node->mem_free = mem;
+               if (node->mem_total && node->mem_free)
Quoted 8 lines

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 181

Quoted 6 lines
tools/perf/util/cputopo.c +6 -0
+                       break;
+       }
+
+       fclose(fp);
+       fp  = NULL;
+       buf = NULL;

No need to make them NULL. Also it'd leak buf..

oops, I'll put free in here

Quoted 6 lines

tools/perf/util/cputopo.c struct cpu_topology *cpu_topology__new(void) · line 183

Quoted 4 lines
tools/perf/util/cputopo.c +2 -0
+
+       ret = -1;

It's not changed yet.

right, will change

thanks,
jirka