public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/3] perf tools: Assorted fixes
@ 2019-02-18 11:39 Jiri Olsa
  2019-02-18 11:39 ` [PATCH 1/3] perf header: Fix wrong node write in NUMA_TOPOLOGY feature Jiri Olsa
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Jiri Olsa @ 2019-02-18 11:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] perf header: Fix wrong node write in NUMA_TOPOLOGY feature
  2019-02-18 11:39 [PATCHv2 0/3] perf tools: Assorted fixes Jiri Olsa
@ 2019-02-18 11:39 ` Jiri Olsa
  2019-02-18 11:39 ` [PATCH 2/3] perf tools: Add cpu_topology object Jiri Olsa
  2019-02-18 11:39 ` [PATCH 3/3] perf tools: Add numa_topology object Jiri Olsa
  2 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2019-02-18 11:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra

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

Fixes: fbe96f29ce4b ("perf tools: Make perf.data more self-descriptive (v8)"
Link: http://lkml.kernel.org/n/tip-rbtlsr9ts23c89rki7d4s5sm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/header.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 61ce197c5362..c66f26ec557a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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;
 	}
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] perf tools: Add cpu_topology object
  2019-02-18 11:39 [PATCHv2 0/3] perf tools: Assorted fixes Jiri Olsa
  2019-02-18 11:39 ` [PATCH 1/3] perf header: Fix wrong node write in NUMA_TOPOLOGY feature Jiri Olsa
@ 2019-02-18 11:39 ` Jiri Olsa
  2019-02-18 11:39 ` [PATCH 3/3] perf tools: Add numa_topology object Jiri Olsa
  2 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2019-02-18 11:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra

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.

Link: http://lkml.kernel.org/n/tip-4g1sdzg0bvd5la96xw06y3en@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 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

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index ca0741c91903..3008d49fa587 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -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
diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
new file mode 100644
index 000000000000..84470ed4e707
--- /dev/null
+++ b/tools/perf/util/cputopo.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <sys/param.h>
+
+#include "cputopo.h"
+#include "cpumap.h"
+#include "util.h"
+
+
+#define CORE_SIB_FMT \
+	"/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
+#define THRD_SIB_FMT \
+	"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
+
+static int build_cpu_topology(struct cpu_topology *tp, int cpu)
+{
+	FILE *fp;
+	char filename[MAXPATHLEN];
+	char *buf = NULL, *p;
+	size_t len = 0;
+	ssize_t sret;
+	u32 i = 0;
+	int ret = -1;
+
+	sprintf(filename, CORE_SIB_FMT, cpu);
+	fp = fopen(filename, "r");
+	if (!fp)
+		goto try_threads;
+
+	sret = getline(&buf, &len, fp);
+	fclose(fp);
+	if (sret <= 0)
+		goto try_threads;
+
+	p = strchr(buf, '\n');
+	if (p)
+		*p = '\0';
+
+	for (i = 0; i < tp->core_sib; i++) {
+		if (!strcmp(buf, tp->core_siblings[i]))
+			break;
+	}
+	if (i == tp->core_sib) {
+		tp->core_siblings[i] = buf;
+		tp->core_sib++;
+		buf = NULL;
+		len = 0;
+	}
+	ret = 0;
+
+try_threads:
+	sprintf(filename, THRD_SIB_FMT, cpu);
+	fp = fopen(filename, "r");
+	if (!fp)
+		goto done;
+
+	if (getline(&buf, &len, fp) <= 0)
+		goto done;
+
+	p = strchr(buf, '\n');
+	if (p)
+		*p = '\0';
+
+	for (i = 0; i < tp->thread_sib; i++) {
+		if (!strcmp(buf, tp->thread_siblings[i]))
+			break;
+	}
+	if (i == tp->thread_sib) {
+		tp->thread_siblings[i] = buf;
+		tp->thread_sib++;
+		buf = NULL;
+	}
+	ret = 0;
+done:
+	if (fp)
+		fclose(fp);
+	free(buf);
+	return ret;
+}
+
+void cpu_topology__delete(struct cpu_topology *tp)
+{
+	u32 i;
+
+	if (!tp)
+		return;
+
+	for (i = 0 ; i < tp->core_sib; i++)
+		zfree(&tp->core_siblings[i]);
+
+	for (i = 0 ; i < tp->thread_sib; i++)
+		zfree(&tp->thread_siblings[i]);
+
+	free(tp);
+}
+
+struct cpu_topology *cpu_topology__new(void)
+{
+	struct cpu_topology *tp = NULL;
+	void *addr;
+	u32 nr, i;
+	size_t sz;
+	long ncpus;
+	int ret = -1;
+	struct cpu_map *map;
+
+	ncpus = cpu__max_present_cpu();
+
+	/* build online CPU map */
+	map = cpu_map__new(NULL);
+	if (map == NULL) {
+		pr_debug("failed to get system cpumap\n");
+		return NULL;
+	}
+
+	nr = (u32)(ncpus & UINT_MAX);
+
+	sz = nr * sizeof(char *);
+	addr = calloc(1, sizeof(*tp) + 2 * sz);
+	if (!addr)
+		goto out_free;
+
+	tp = addr;
+	addr += sizeof(*tp);
+	tp->core_siblings = addr;
+	addr += sz;
+	tp->thread_siblings = addr;
+
+	for (i = 0; i < nr; i++) {
+		if (!cpu_map__has(map, i))
+			continue;
+
+		ret = build_cpu_topology(tp, i);
+		if (ret < 0)
+			break;
+	}
+
+out_free:
+	cpu_map__put(map);
+	if (ret) {
+		cpu_topology__delete(tp);
+		tp = NULL;
+	}
+	return tp;
+}
diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h
new file mode 100644
index 000000000000..4b5f4112b6f8
--- /dev/null
+++ b/tools/perf/util/cputopo.h
@@ -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 */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c66f26ec557a..80ac57e6d38f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -39,6 +39,7 @@
 #include "tool.h"
 #include "time-utils.h"
 #include "units.h"
+#include "cputopo.h"
 
 #include "sane_ctype.h"
 
@@ -557,158 +558,15 @@ static int write_cmdline(struct feat_fd *ff,
 	return 0;
 }
 
-#define CORE_SIB_FMT \
-	"/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
-#define THRD_SIB_FMT \
-	"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
-
-struct cpu_topo {
-	u32 core_sib;
-	u32 thread_sib;
-	char **core_siblings;
-	char **thread_siblings;
-};
-
-static int build_cpu_topo(struct cpu_topo *tp, int cpu)
-{
-	FILE *fp;
-	char filename[MAXPATHLEN];
-	char *buf = NULL, *p;
-	size_t len = 0;
-	ssize_t sret;
-	u32 i = 0;
-	int ret = -1;
-
-	sprintf(filename, CORE_SIB_FMT, cpu);
-	fp = fopen(filename, "r");
-	if (!fp)
-		goto try_threads;
-
-	sret = getline(&buf, &len, fp);
-	fclose(fp);
-	if (sret <= 0)
-		goto try_threads;
-
-	p = strchr(buf, '\n');
-	if (p)
-		*p = '\0';
-
-	for (i = 0; i < tp->core_sib; i++) {
-		if (!strcmp(buf, tp->core_siblings[i]))
-			break;
-	}
-	if (i == tp->core_sib) {
-		tp->core_siblings[i] = buf;
-		tp->core_sib++;
-		buf = NULL;
-		len = 0;
-	}
-	ret = 0;
-
-try_threads:
-	sprintf(filename, THRD_SIB_FMT, cpu);
-	fp = fopen(filename, "r");
-	if (!fp)
-		goto done;
-
-	if (getline(&buf, &len, fp) <= 0)
-		goto done;
-
-	p = strchr(buf, '\n');
-	if (p)
-		*p = '\0';
-
-	for (i = 0; i < tp->thread_sib; i++) {
-		if (!strcmp(buf, tp->thread_siblings[i]))
-			break;
-	}
-	if (i == tp->thread_sib) {
-		tp->thread_siblings[i] = buf;
-		tp->thread_sib++;
-		buf = NULL;
-	}
-	ret = 0;
-done:
-	if(fp)
-		fclose(fp);
-	free(buf);
-	return ret;
-}
-
-static void free_cpu_topo(struct cpu_topo *tp)
-{
-	u32 i;
-
-	if (!tp)
-		return;
-
-	for (i = 0 ; i < tp->core_sib; i++)
-		zfree(&tp->core_siblings[i]);
-
-	for (i = 0 ; i < tp->thread_sib; i++)
-		zfree(&tp->thread_siblings[i]);
-
-	free(tp);
-}
-
-static struct cpu_topo *build_cpu_topology(void)
-{
-	struct cpu_topo *tp = NULL;
-	void *addr;
-	u32 nr, i;
-	size_t sz;
-	long ncpus;
-	int ret = -1;
-	struct cpu_map *map;
-
-	ncpus = cpu__max_present_cpu();
-
-	/* build online CPU map */
-	map = cpu_map__new(NULL);
-	if (map == NULL) {
-		pr_debug("failed to get system cpumap\n");
-		return NULL;
-	}
-
-	nr = (u32)(ncpus & UINT_MAX);
-
-	sz = nr * sizeof(char *);
-	addr = calloc(1, sizeof(*tp) + 2 * sz);
-	if (!addr)
-		goto out_free;
-
-	tp = addr;
-	addr += sizeof(*tp);
-	tp->core_siblings = addr;
-	addr += sz;
-	tp->thread_siblings = addr;
-
-	for (i = 0; i < nr; i++) {
-		if (!cpu_map__has(map, i))
-			continue;
-
-		ret = build_cpu_topo(tp, i);
-		if (ret < 0)
-			break;
-	}
-
-out_free:
-	cpu_map__put(map);
-	if (ret) {
-		free_cpu_topo(tp);
-		tp = NULL;
-	}
-	return tp;
-}
 
 static int write_cpu_topology(struct feat_fd *ff,
 			      struct perf_evlist *evlist __maybe_unused)
 {
-	struct cpu_topo *tp;
+	struct cpu_topology *tp;
 	u32 i;
 	int ret, j;
 
-	tp = build_cpu_topology();
+	tp = cpu_topology__new();
 	if (!tp)
 		return -1;
 
@@ -746,7 +604,7 @@ static int write_cpu_topology(struct feat_fd *ff,
 			return ret;
 	}
 done:
-	free_cpu_topo(tp);
+	cpu_topology__delete(tp);
 	return ret;
 }
 
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] perf tools: Add numa_topology object
  2019-02-18 11:39 [PATCHv2 0/3] perf tools: Assorted fixes Jiri Olsa
  2019-02-18 11:39 ` [PATCH 1/3] perf header: Fix wrong node write in NUMA_TOPOLOGY feature Jiri Olsa
  2019-02-18 11:39 ` [PATCH 2/3] perf tools: Add cpu_topology object Jiri Olsa
@ 2019-02-18 11:39 ` Jiri Olsa
  2019-02-18 14:08   ` Namhyung Kim
  2 siblings, 1 reply; 6+ messages in thread
From: Jiri Olsa @ 2019-02-18 11:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, Alexander Shishkin,
	Peter Zijlstra

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.

Link: http://lkml.kernel.org/n/tip-rn15st6hjj7txg2i88v7yff4@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 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(-)

diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
index 84470ed4e707..daac3cf90b12 100644
--- a/tools/perf/util/cputopo.c
+++ b/tools/perf/util/cputopo.c
@@ -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);
+}
diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h
index 4b5f4112b6f8..47a97e71acdf 100644
--- a/tools/perf/util/cputopo.h
+++ b/tools/perf/util/cputopo.h
@@ -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 */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 80ac57e6d38f..a2323d777dae 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] perf tools: Add numa_topology object
  2019-02-18 11:39 ` [PATCH 3/3] perf tools: Add numa_topology object Jiri Olsa
@ 2019-02-18 14:08   ` Namhyung Kim
  2019-02-18 14:20     ` Jiri Olsa
  0 siblings, 1 reply; 6+ messages in thread
From: Namhyung Kim @ 2019-02-18 14:08 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, lkml, Ingo Molnar, Alexander Shishkin,
	Peter Zijlstra

Hi Jirka,

On Mon, Feb 18, 2019 at 8:39 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> 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.
>
> Link: http://lkml.kernel.org/n/tip-rn15st6hjj7txg2i88v7yff4@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  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(-)
>
> diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
> index 84470ed4e707..daac3cf90b12 100644
> --- a/tools/perf/util/cputopo.c
> +++ b/tools/perf/util/cputopo.c
> @@ -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);

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


> +       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;

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


> +
> +       ret = -1;

It's not changed yet.

Thanks,
Namhyung


> +       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);
> +}
> diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h
> index 4b5f4112b6f8..47a97e71acdf 100644
> --- a/tools/perf/util/cputopo.h
> +++ b/tools/perf/util/cputopo.h
> @@ -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 */
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 80ac57e6d38f..a2323d777dae 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -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
>


-- 
Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] perf tools: Add numa_topology object
  2019-02-18 14:08   ` Namhyung Kim
@ 2019-02-18 14:20     ` Jiri Olsa
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2019-02-18 14:20 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, lkml, Ingo Molnar,
	Alexander Shishkin, Peter Zijlstra

On Mon, Feb 18, 2019 at 11:08:55PM +0900, Namhyung Kim wrote:
> Hi Jirka,
> 
> On Mon, Feb 18, 2019 at 8:39 PM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > 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.
> >
> > Link: http://lkml.kernel.org/n/tip-rn15st6hjj7txg2i88v7yff4@git.kernel.org
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  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(-)
> >
> > diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
> > index 84470ed4e707..daac3cf90b12 100644
> > --- a/tools/perf/util/cputopo.c
> > +++ b/tools/perf/util/cputopo.c
> > @@ -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);
> 
> 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 ;-)

> 
> 
> > +       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;
> 
> No need to make them NULL.  Also it'd leak buf..

oops, I'll put free in here

> 
> 
> > +
> > +       ret = -1;
> 
> It's not changed yet.

right, will change

thanks,
jirka

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-02-18 14:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-18 11:39 [PATCHv2 0/3] perf tools: Assorted fixes Jiri Olsa
2019-02-18 11:39 ` [PATCH 1/3] perf header: Fix wrong node write in NUMA_TOPOLOGY feature Jiri Olsa
2019-02-18 11:39 ` [PATCH 2/3] perf tools: Add cpu_topology object Jiri Olsa
2019-02-18 11:39 ` [PATCH 3/3] perf tools: Add numa_topology object Jiri Olsa
2019-02-18 14:08   ` Namhyung Kim
2019-02-18 14:20     ` Jiri Olsa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox