lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1450804030-29193-10-git-send-email-namhyung@kernel.org>
Date:	Wed, 23 Dec 2015 02:07:06 +0900
From:	Namhyung Kim <namhyung@...nel.org>
To:	Arnaldo Carvalho de Melo <acme@...nel.org>
Cc:	Ingo Molnar <mingo@...nel.org>,
	Peter Zijlstra <peterz@...radead.org>,
	Jiri Olsa <jolsa@...hat.com>,
	LKML <linux-kernel@...r.kernel.org>,
	David Ahern <dsahern@...il.com>,
	Steven Rostedt <rostedt@...dmis.org>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Andi Kleen <andi@...stfloor.org>,
	Wang Nan <wangnan0@...wei.com>
Subject: [PATCH 09/13] perf tools: Support shortcuts for events in dynamic sort keys

The dynamic sort key requires event name but specifying full event name
is rather inconvenient.  This patch adds more ways to identify the event
in a more compact way.

  1. If session has just one event, event name can be omitted.
  2. Events can be accessed by index preceded by a percent sign.
  3. A part of the name can be used, if it's not ambiguous.  The partial
     name should not contain ':' in it.
  4. Full system + event name is still used, it should contain ':'.

So in the below example all does same thing:

  $ perf record -e sched:sched_switch -a sleep 1

  $ perf report -s next_pid,next_comm
  $ perf report -s %1.next_pid,%1.next_comm
  $ perf report -s switch.next_pid,switch.next_comm
  $ perf report -s sched:sched_switch.next_pid,sched:sched_switch_.next_comm

Cc: Steven Rostedt <rostedt@...dmis.org>
Signed-off-by: Namhyung Kim <namhyung@...nel.org>
---
 tools/perf/util/sort.c | 107 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 87 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index df9e5989e209..78496f0555ec 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1827,10 +1827,90 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
 	return hde;
 }
 
+static int parse_field_name(char *str, char **event, char **field, char **opt)
+{
+	char *event_name, *field_name, *opt_name;
+
+	event_name = str;
+	field_name = strchr(str, '.');
+
+	if (field_name) {
+		*field_name++ = '\0';
+	} else {
+		event_name = NULL;
+		field_name = str;
+	}
+
+	opt_name = strchr(field_name, '/');
+	if (opt_name)
+		*opt_name++ = '\0';
+
+	*event = event_name;
+	*field = field_name;
+	*opt   = opt_name;
+
+	return 0;
+}
+
+/* find match evsel using a given event name.  The event name can be:
+ *   1. NULL - only valid for single event session
+ *   2. '%' + event index (e.g. '%1' for first event)
+ *   3. full event name (e.g. sched:sched_switch)
+ *   4. partial event name (should not contain ':')
+ */
+static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
+{
+	struct perf_evsel *evsel = NULL;
+	struct perf_evsel *pos;
+	bool full_name;
+
+	/* case 1 */
+	if (event_name == NULL) {
+		if (evlist->nr_entries != 1) {
+			pr_debug("event name should be given\n");
+			return NULL;
+		}
+
+		return perf_evlist__first(evlist);
+	}
+
+	/* case 2 */
+	if (event_name[0] == '%') {
+		int nr = strtol(event_name+1, NULL, 0);
+
+		if (nr > evlist->nr_entries)
+			return NULL;
+
+		evsel = perf_evlist__first(evlist);
+		while (--nr > 0)
+			evsel = perf_evsel__next(evsel);
+
+		return evsel;
+	}
+
+	full_name = !!strchr(event_name, ':');
+	evlist__for_each(evlist, pos) {
+		/* case 3 */
+		if (full_name && !strcmp(pos->name, event_name))
+			return pos;
+		/* case 4 */
+		if (!full_name && strstr(pos->name, event_name)) {
+			if (evsel) {
+				pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
+					 event_name, evsel->name, pos->name);
+				return NULL;
+			}
+			evsel = pos;
+		}
+	}
+
+	return evsel;
+}
+
 static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 {
-	char *str, *event_name, *field_name, *raw_opt;
-	struct perf_evsel *evsel, *pos;
+	char *str, *event_name, *field_name, *opt_name;
+	struct perf_evsel *evsel;
 	struct format_field *field;
 	struct hpp_dynamic_entry *hde;
 	bool raw_trace = symbol_conf.raw_trace;
@@ -1843,34 +1923,21 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
 	if (str == NULL)
 		return -ENOMEM;
 
-	event_name = str;
-	field_name = strchr(str, '.');
-	if (field_name == NULL) {
+	if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
 		ret = -EINVAL;
 		goto out;
 	}
-	*field_name++ = '\0';
 
-	raw_opt = strchr(field_name, '/');
-	if (raw_opt) {
-		*raw_opt++ = '\0';
-
-		if (strcmp(raw_opt, "raw")) {
-			pr_err("Unsupported field option %s\n", raw_opt);
+	if (opt_name) {
+		if (strcmp(opt_name, "raw")) {
+			pr_debug("unsupported field option %s\n", opt_name);
 			ret = -EINVAL;
 			goto out;
 		}
 		raw_trace = true;
 	}
 
-	evsel = NULL;
-	evlist__for_each(evlist, pos) {
-		if (!strcmp(pos->name, event_name)) {
-			evsel = pos;
-			break;
-		}
-	}
-
+	evsel = find_evsel(evlist, event_name);
 	if (evsel == NULL) {
 		pr_debug("Cannot find event: %s\n", event_name);
 		ret = -ENOENT;
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ