2010-11-09 21:18:30

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 0/7] perf trace command-line cleanup

From: Tom Zanussi <[email protected]>

There are currently some inconsistencies in perf trace command-line
handling - for example, the system-wide param is hard-coded into the
canned scripts, and the user doesn't have any option to avoid it.
This patchset removes that limitation and cleans up some related
complications introduced by live-mode. It also more clearly documents
usage, and fixes up a couple other minor problems.

This patchset can also be pulled from here:

git://github.com/zanussi/linux-2.6.git perf-trace-updates


Tom Zanussi (7):
perf trace scripting: fix some small memory leaks and missing error
checks
perf trace scripting: remove system-wide param from shell scripts
perf record: make the record options available outside perf record
perf trace record: handle commands correctly
perf trace: live-mode command-line cleanup
perf trace: update Documentation with new perf trace variants
perf trace: update usage

tools/perf/Documentation/perf-trace.txt | 57 +++++-
tools/perf/builtin-record.c | 10 +-
tools/perf/builtin-trace.c | 209 ++++++++++++++------
tools/perf/scripts/perl/bin/failed-syscalls-record | 2 +-
tools/perf/scripts/perl/bin/rw-by-file-record | 2 +-
tools/perf/scripts/perl/bin/rw-by-pid-record | 2 +-
tools/perf/scripts/perl/bin/rwtop-record | 2 +-
tools/perf/scripts/perl/bin/wakeup-latency-record | 2 +-
tools/perf/scripts/perl/bin/workqueue-stats-record | 2 +-
.../python/bin/failed-syscalls-by-pid-record | 2 +-
.../scripts/python/bin/futex-contention-record | 2 +-
tools/perf/scripts/python/bin/netdev-times-record | 2 +-
.../perf/scripts/python/bin/sched-migration-record | 2 +-
tools/perf/scripts/python/bin/sctop-record | 2 +-
.../python/bin/syscall-counts-by-pid-record | 2 +-
.../perf/scripts/python/bin/syscall-counts-record | 2 +-
16 files changed, 217 insertions(+), 85 deletions(-)

--
Tom Zanussi, Intel Open Source Technology Center


2010-11-09 21:18:34

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 1/7] perf trace scripting: fix some small memory leaks and missing error checks

From: Tom Zanussi <[email protected]>

Free the other two fields of script_desc which somehow got overlooked,
free malloc'ed args in case exec fails, and add missing checks for
failed mallocs.

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/builtin-trace.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2f8df45..368e624 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -337,6 +337,8 @@ static struct script_desc *script_desc__new(const char *name)
static void script_desc__delete(struct script_desc *s)
{
free(s->name);
+ free(s->half_liner);
+ free(s->args);
free(s);
}

@@ -626,6 +628,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
close(live_pipe[0]);

__argv = malloc(6 * sizeof(const char *));
+ if (!__argv)
+ die("malloc");
+
__argv[0] = "/bin/sh";
__argv[1] = record_script_path;
__argv[2] = "-q";
@@ -634,6 +639,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
__argv[5] = NULL;

execvp("/bin/sh", (char **)__argv);
+ free(__argv);
exit(-1);
}

@@ -641,6 +647,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
close(live_pipe[1]);

__argv = malloc((argc + 3) * sizeof(const char *));
+ if (!__argv)
+ die("malloc");
__argv[0] = "/bin/sh";
__argv[1] = report_script_path;
for (i = 2; i < argc; i++)
@@ -650,6 +658,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
__argv[i++] = NULL;

execvp("/bin/sh", (char **)__argv);
+ free(__argv);
exit(-1);
}

@@ -661,6 +670,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
}

__argv = malloc((argc + 1) * sizeof(const char *));
+ if (!__argv)
+ die("malloc");
__argv[0] = "/bin/sh";
__argv[1] = script_path;
for (i = 3; i < argc; i++)
@@ -668,7 +679,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
__argv[argc - 1] = NULL;

execvp("/bin/sh", (char **)__argv);
+ free(__argv);
exit(-1);
}

--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:18:38

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 2/7] perf trace scripting: remove system-wide param from shell scripts

From: Tom Zanussi <[email protected]>

Including -a unconditionally when recording doesn't allow for the
option of running scripts without it. Future patches will add add it
back if needed at run-time.

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/scripts/perl/bin/failed-syscalls-record | 2 +-
tools/perf/scripts/perl/bin/rw-by-file-record | 2 +-
tools/perf/scripts/perl/bin/rw-by-pid-record | 2 +-
tools/perf/scripts/perl/bin/rwtop-record | 2 +-
tools/perf/scripts/perl/bin/wakeup-latency-record | 2 +-
tools/perf/scripts/perl/bin/workqueue-stats-record | 2 +-
.../python/bin/failed-syscalls-by-pid-record | 2 +-
.../scripts/python/bin/futex-contention-record | 2 +-
tools/perf/scripts/python/bin/netdev-times-record | 2 +-
.../perf/scripts/python/bin/sched-migration-record | 2 +-
tools/perf/scripts/python/bin/sctop-record | 2 +-
.../python/bin/syscall-counts-by-pid-record | 2 +-
.../perf/scripts/python/bin/syscall-counts-record | 2 +-
13 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
index eb5846b..8104895 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-record
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e raw_syscalls:sys_exit $@
+perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
index 5bfaae5..33efc86 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-record
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -1,3 +1,3 @@
#!/bin/bash
-perf record -a -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@
+perf record -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@

diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
index 6e0b2f7..7cb9db2 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-record
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
+perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record
index 6e0b2f7..7cb9db2 100644
--- a/tools/perf/scripts/perl/bin/rwtop-record
+++ b/tools/perf/scripts/perl/bin/rwtop-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
+perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
index 9f2acaa..464251a 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-record
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -1,5 +1,5 @@
#!/bin/bash
-perf record -a -e sched:sched_switch -e sched:sched_wakeup $@
+perf record -e sched:sched_switch -e sched:sched_wakeup $@



diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
index 85301f2..8edda90 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-record
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
+perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
index eb5846b..8104895 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e raw_syscalls:sys_exit $@
+perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
index 5ecbb43..b1495c9 100644
--- a/tools/perf/scripts/python/bin/futex-contention-record
+++ b/tools/perf/scripts/python/bin/futex-contention-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
+perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
index d931a82..558754b 100644
--- a/tools/perf/scripts/python/bin/netdev-times-record
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -1,5 +1,5 @@
#!/bin/bash
-perf record -a -e net:net_dev_xmit -e net:net_dev_queue \
+perf record -e net:net_dev_xmit -e net:net_dev_queue \
-e net:netif_receive_skb -e net:netif_rx \
-e skb:consume_skb -e skb:kfree_skb \
-e skb:skb_copy_datagram_iovec -e napi:napi_poll \
diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record
index 17a3e9b..7493fdd 100644
--- a/tools/perf/scripts/python/bin/sched-migration-record
+++ b/tools/perf/scripts/python/bin/sched-migration-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -m 16384 -a -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
+perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
index 1fc5998..4efbfaa 100644
--- a/tools/perf/scripts/python/bin/sctop-record
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e raw_syscalls:sys_enter $@
+perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
index 1fc5998..4efbfaa 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
@@ -1,2 +1,2 @@
#!/bin/bash
-perf record -a -e raw_syscalls:sys_enter $@
+perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
index 1fc5998..4efbfaa 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -1,3 +1,2 @@
#!/bin/bash
-perf record -a -e raw_syscalls:sys_enter $@
+perf record -e raw_syscalls:sys_enter $@
--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:18:49

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 6/7] perf trace: update Documentation with new perf trace variants

From: Tom Zanussi <[email protected]>

Add documentation describing new 'perf trace' command changes
e.g. <command> handling and live-mode/top variants.

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/Documentation/perf-trace.txt | 57 ++++++++++++++++++++++++++----
1 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 122ec9d..26aff6b 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -8,7 +8,11 @@ perf-trace - Read perf.data (created by perf record) and display trace output
SYNOPSIS
--------
[verse]
-'perf trace' {record <script> | report <script> [args] }
+'perf trace' [<options>]
+'perf trace' [<options>] record <script> [<record-options>] <command>
+'perf trace' [<options>] report <script> [script-args]
+'perf trace' [<options>] <script> <required-script-args> [<record-options>] <command>
+'perf trace' [<options>] <top-script> [script-args]

DESCRIPTION
-----------
@@ -24,23 +28,53 @@ There are several variants of perf trace:
available via 'perf trace -l'). The following variants allow you to
record and run those scripts:

- 'perf trace record <script>' to record the events required for 'perf
- trace report'. <script> is the name displayed in the output of
- 'perf trace --list' i.e. the actual script name minus any language
- extension.
+ 'perf trace record <script> <command>' to record the events required
+ for 'perf trace report'. <script> is the name displayed in the
+ output of 'perf trace --list' i.e. the actual script name minus any
+ language extension. If <command> is not specified, the events are
+ recorded using the -a (system-wide) 'perf record' option.

- 'perf trace report <script>' to run and display the results of
- <script>. <script> is the name displayed in the output of 'perf
+ 'perf trace report <script> [args]' to run and display the results
+ of <script>. <script> is the name displayed in the output of 'perf
trace --list' i.e. the actual script name minus any language
extension. The perf.data output from a previous run of 'perf trace
record <script>' is used and should be present for this command to
- succeed.
+ succeed. [args] refers to the (mainly optional) args expected by
+ the script.
+
+ 'perf trace <script> <required-script-args> <command>' to both
+ record the events required for <script> and to run the <script>
+ using 'live-mode' i.e. without writing anything to disk. <script>
+ is the name displayed in the output of 'perf trace --list' i.e. the
+ actual script name minus any language extension. If <command> is
+ not specified, the events are recorded using the -a (system-wide)
+ 'perf record' option. If <script> has any required args, they
+ should be specified before <command>. This mode doesn't allow for
+ optional script args to be specified; if optional script args are
+ desired, they can be specified using separate 'perf trace record'
+ and 'perf trace report' commands, with the stdout of the record step
+ piped to the stdin of the report script, using the '-o -' and '-i -'
+ options of the corresponding commands.
+
+ 'perf trace <top-script>' to both record the events required for
+ <top-script> and to run the <top-script> using 'live-mode'
+ i.e. without writing anything to disk. <top-script> is the name
+ displayed in the output of 'perf trace --list' i.e. the actual
+ script name minus any language extension; a <top-script> is defined
+ as any script name ending with the string 'top'.
+
+ [<record-options>] can be passed to the record steps of 'perf trace
+ record' and 'live-mode' variants; this isn't possible however for
+ <top-script> 'live-mode' or 'perf trace report' variants.

See the 'SEE ALSO' section for links to language-specific
information on how to write and run your own trace scripts.

OPTIONS
-------
+<command>...::
+ Any command you can specify in a shell.
+
-D::
--dump-raw-trace=::
Display verbose dump of the trace data.
@@ -64,7 +98,13 @@ OPTIONS
Generate perf-trace.[ext] starter script for given language,
using current perf.data.

+-a::
+ Force system-wide collection. Scripts run without a <command>
+ normally use -a by default, while scripts run with a <command>
+ normally don't - this option allows the latter to be run in
+ system-wide mode.
+
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-trace-perl[1],
--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:19:17

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 5/7] perf trace: live-mode command-line cleanup

From: Tom Zanussi <[email protected]>

This patch attempts to make the perf trace command-line for live-mode
commands more user-friendly and consistent with other perf commands.

The main change it makes is to allow <commands> to be run as part of
perf trace live-mode commands, as other perf commands do, instead of
the system-wide traces they're currently hard-coded to by the shell
scripts.

With this patch, the following live-mode trace now works as expected:

$ perf trace rw-by-pid ls -al

The previous system-wide behavior for this command would still be
available by explicitly specifying -a:

$ perf trace rw-by-pid -a ls -al

and if no <command> is specified, the output is also system-wide:

$ perf trace rw-by-pid

Because live-mode requires both record and report steps to be invoked,
it isn't always possible to know which args to send to the report and
which to send to the record steps - mainly this is the case for report
scripts with optional args - in those cases it would be necessary to
use separate 'perf trace record' and 'perf trace report' steps.

For example:

$ perf trace syscall-counts ls

Here we can't decide whether ls should be passed as a param to the
syscall-counts script or whether we should invoke ls as a <command>.
In these cases, we just say that we'll ignore optional script params
and always interpret the extra arguments as a <command>.

If the user instead wants the other interpretation, that can be
accomplished by using separate record and report commands explicitly:

$ perf trace record syscall-counts
$ perf trace report syscall-counts ls

So the rules that this patch implements, which seem to make the most
intuitive sense for live-mode commands:

- for commands with optional args and commands with no args, no args
are sent to the report script, all are sent to the record step

- for 'top' commands i.e. that end with 'top', <commands> can't be
used - all extra args are send to the report script as params

- for commands with required args, the n required args are taken to be
the first n args after the script name and sent to the report
script, and the rest are sent to the record step

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/builtin-trace.c | 165 +++++++++++++++++++++++++++++---------------
1 files changed, 108 insertions(+), 57 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0de7fcb..0483e28 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -330,7 +330,7 @@ static struct script_desc *script_desc__new(const char *name)
{
struct script_desc *s = zalloc(sizeof(*s));

- if (s != NULL)
+ if (s != NULL && name)
s->name = strdup(name);

return s;
@@ -541,6 +541,34 @@ static char *get_script_path(const char *script_root, const char *suffix)
return path;
}

+static bool is_top_script(const char *script_path)
+{
+ return ends_with((char *)script_path, "top") == NULL ? false : true;
+}
+
+static int has_required_arg(char *script_path)
+{
+ struct script_desc *desc;
+ int n_args = 0;
+ char *p;
+
+ desc = script_desc__new(NULL);
+
+ if (read_script_info(desc, script_path))
+ goto out;
+
+ if (!desc->args)
+ goto out;
+
+ for (p = desc->args; *p; p++)
+ if (*p == '<')
+ n_args++;
+out:
+ script_desc__delete(desc);
+
+ return n_args;
+}
+
static const char * const trace_usage[] = {
"perf trace [<options>] <command>",
NULL
@@ -584,48 +612,65 @@ static bool have_cmd(int argc, const char **argv)

int cmd_trace(int argc, const char **argv, const char *prefix __used)
{
+ char *rec_script_path = NULL;
+ char *rep_script_path = NULL;
struct perf_session *session;
- const char *suffix = NULL;
+ char *script_path = NULL;
const char **__argv;
- char *script_path;
- int i, err;
+ bool system_wide;
+ int i, j, err;

- if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) {
- if (argc < 3) {
- fprintf(stderr,
- "Please specify a record script\n");
- return -1;
- }
- suffix = RECORD_SUFFIX;
+ setup_scripting();
+
+ argc = parse_options(argc, argv, options, trace_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+
+ if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
+ rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
+ if (!rec_script_path)
+ return cmd_record(argc, argv, NULL);
}

- if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) {
- if (argc < 3) {
+ if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
+ rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
+ if (!rep_script_path) {
fprintf(stderr,
- "Please specify a report script\n");
+ "Please specify a valid report script"
+ "(see 'perf trace -l' for listing)\n");
return -1;
}
- suffix = REPORT_SUFFIX;
}

/* make sure PERF_EXEC_PATH is set for scripts */
perf_set_argv_exec_path(perf_exec_path());

- if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) {
- char *record_script_path, *report_script_path;
+ if (argc && !script_name && !rec_script_path && !rep_script_path) {
int live_pipe[2];
+ int rep_args;
pid_t pid;

- record_script_path = get_script_path(argv[1], RECORD_SUFFIX);
- if (!record_script_path) {
- fprintf(stderr, "record script not found\n");
- return -1;
+ rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
+ rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
+
+ if (!rec_script_path && !rep_script_path) {
+ fprintf(stderr, " Couldn't find script %s\n\n See perf"
+ " trace -l for available scripts.\n", argv[0]);
+ usage_with_options(trace_usage, options);
}

- report_script_path = get_script_path(argv[1], REPORT_SUFFIX);
- if (!report_script_path) {
- fprintf(stderr, "report script not found\n");
- return -1;
+ if (is_top_script(argv[0])) {
+ rep_args = argc - 1;
+ } else {
+ int rec_args;
+
+ rep_args = has_required_arg(rep_script_path);
+ rec_args = (argc - 1) - rep_args;
+ if (rec_args < 0) {
+ fprintf(stderr, " %s script requires options."
+ "\n\n See perf trace -l for available "
+ "scripts and options.\n", argv[0]);
+ usage_with_options(trace_usage, options);
+ }
}

if (pipe(live_pipe) < 0) {
@@ -640,19 +685,30 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
}

if (!pid) {
+ system_wide = true;
+ j = 0;
+
dup2(live_pipe[1], 1);
close(live_pipe[0]);

- __argv = malloc(6 * sizeof(const char *));
+ if (!is_top_script(argv[0]))
+ system_wide = !have_cmd(argc - rep_args,
+ &argv[rep_args]);
+
+ __argv = malloc((argc + 6) * sizeof(const char *));
if (!__argv)
die("malloc");

- __argv[0] = "/bin/sh";
- __argv[1] = record_script_path;
- __argv[2] = "-q";
- __argv[3] = "-o";
- __argv[4] = "-";
- __argv[5] = NULL;
+ __argv[j++] = "/bin/sh";
+ __argv[j++] = rec_script_path;
+ if (system_wide)
+ __argv[j++] = "-a";
+ __argv[j++] = "-q";
+ __argv[j++] = "-o";
+ __argv[j++] = "-";
+ for (i = rep_args + 1; i < argc; i++)
+ __argv[j++] = argv[i];
+ __argv[j++] = NULL;

execvp("/bin/sh", (char **)__argv);
free(__argv);
@@ -662,43 +718,43 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
dup2(live_pipe[0], 0);
close(live_pipe[1]);

- __argv = malloc((argc + 3) * sizeof(const char *));
+ __argv = malloc((argc + 4) * sizeof(const char *));
if (!__argv)
die("malloc");
- __argv[0] = "/bin/sh";
- __argv[1] = report_script_path;
- for (i = 2; i < argc; i++)
- __argv[i] = argv[i];
- __argv[i++] = "-i";
- __argv[i++] = "-";
- __argv[i++] = NULL;
+ j = 0;
+ __argv[j++] = "/bin/sh";
+ __argv[j++] = rep_script_path;
+ for (i = 1; i < rep_args + 1; i++)
+ __argv[j++] = argv[i];
+ __argv[j++] = "-i";
+ __argv[j++] = "-";
+ __argv[j++] = NULL;

execvp("/bin/sh", (char **)__argv);
free(__argv);
exit(-1);
}

- if (suffix) {
- bool system_wide = false;
- int j = 0;
+ if (rec_script_path)
+ script_path = rec_script_path;
+ if (rep_script_path)
+ script_path = rep_script_path;

- script_path = get_script_path(argv[2], suffix);
- if (!script_path) {
- fprintf(stderr, "script not found\n");
- return -1;
- }
+ if (script_path) {
+ system_wide = false;
+ j = 0;

- if (!strcmp(suffix, RECORD_SUFFIX))
- system_wide = !have_cmd(argc - 2, &argv[2]);
+ if (rec_script_path)
+ system_wide = !have_cmd(argc - 1, &argv[1]);

- __argv = malloc((argc + 1) * sizeof(const char *));
+ __argv = malloc((argc + 2) * sizeof(const char *));
if (!__argv)
die("malloc");
__argv[j++] = "/bin/sh";
__argv[j++] = script_path;
if (system_wide)
__argv[j++] = "-a";
- for (i = 3; i < argc; i++)
+ for (i = 2; i < argc; i++)
__argv[j++] = argv[i];
__argv[j++] = NULL;

@@ -707,11 +763,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
exit(-1);
}

- setup_scripting();
-
- argc = parse_options(argc, argv, options, trace_usage,
- PARSE_OPT_STOP_AT_NON_OPTION);
-
if (symbol__init() < 0)
return -1;
if (!script_name)
--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:18:35

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 3/7] perf record: make the record options available outside perf record

From: Tom Zanussi <[email protected]>

Other perf commands that invoke perf record, such as perf trace, may
want to reuse the options used by perf record.

This makes them non-static and renames them to avoid clashes with
other 'options' variables.

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/builtin-record.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4e75583..93bd2ff 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -790,7 +790,7 @@ static const char * const record_usage[] = {

static bool force, append_file;

-static const struct option options[] = {
+const struct option record_options[] = {
OPT_CALLBACK('e', "event", NULL, "event",
"event selector. use 'perf list' to list available events",
parse_events),
@@ -839,16 +839,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
{
int i, j, err = -ENOMEM;

- argc = parse_options(argc, argv, options, record_usage,
+ argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc && target_pid == -1 && target_tid == -1 &&
!system_wide && !cpu_list)
- usage_with_options(record_usage, options);
+ usage_with_options(record_usage, record_options);

if (force && append_file) {
fprintf(stderr, "Can't overwrite and append at the same time."
" You need to choose between -f and -A");
- usage_with_options(record_usage, options);
+ usage_with_options(record_usage, record_options);
} else if (append_file) {
write_mode = WRITE_APPEND;
} else {
@@ -871,8 +871,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
if (thread_num <= 0) {
fprintf(stderr, "Can't find all threads of pid %d\n",
target_pid);
- usage_with_options(record_usage, options);
+ usage_with_options(record_usage, record_options);
}
} else {
all_tids=malloc(sizeof(pid_t));
--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:18:47

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 7/7] perf trace: update usage

From: Tom Zanussi <[email protected]>

Update usage to reflect the different perf trace variants.

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/builtin-trace.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0483e28..86cfe38 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -570,7 +570,11 @@ out:
}

static const char * const trace_usage[] = {
- "perf trace [<options>] <command>",
+ "perf trace [<options>]",
+ "perf trace [<options>] record <script> [<record-options>] <command>",
+ "perf trace [<options>] report <script> [script-args]",
+ "perf trace [<options>] <script> [<record-options>] <command>",
+ "perf trace [<options>] <top-script> [script-args]",
NULL
};

--
Tom Zanussi, Intel Open Source Technology Center

2010-11-09 21:19:36

by Tom Zanussi

[permalink] [raw]
Subject: [PATCH 4/7] perf trace record: handle commands correctly

From: Tom Zanussi <[email protected]>

Because the perf-trace shell scripts hard-coded the use of the
perf-record system-wide param, a perf trace record session was always
system wide, even if it was given a command.

If given a command, perf trace record now only records the events for
the command, as users expect.

If no command is given, or if the '-a' option is used, the recorded
events are system-wide, as before.

root@tropicana:~# perf trace record syscall-counts ls -al
root@tropicana:~# perf trace
ls-23152 [000] 39984.890387: sys_enter: NR 12 (0, 0, 0, 0, 0, 0)
ls-23152 [000] 39984.890404: sys_enter: NR 9 (0, 0, 0, 0, 0, 0)

root@tropicana:~# perf trace record syscall-counts -a ls -al
root@tropicana:~# perf trace
npviewer.bin-22297 [000] 39831.102709: sys_enter: NR 168 (0, 0, 0, 0, 0, 0)
ls-23111 [000] 39831.107679: sys_enter: NR 59 (0, 0, 0, 0, 0, 0)

Signed-off-by: Tom Zanussi <[email protected]>
---
tools/perf/builtin-trace.c | 32 ++++++++++++++++++++++++++++----
1 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 368e624..0de7fcb 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,6 +10,7 @@
#include "util/symbol.h"
#include "util/thread.h"
#include "util/trace-event.h"
+#include "util/parse-options.h"
#include "util/util.h"

static char const *script_name;
@@ -17,6 +18,7 @@ static char const *generate_script_lang;
static bool debug_mode;
static u64 last_timestamp;
static u64 nr_unordered;
+extern const struct option record_options[];

static int default_start_script(const char *script __unused,
int argc __unused,
@@ -566,6 +568,20 @@ static const struct option options[] = {
OPT_END()
};

+static bool have_cmd(int argc, const char **argv)
+{
+ char **__argv = malloc(sizeof(const char *) * argc);
+
+ if (!__argv)
+ die("malloc");
+ memcpy(__argv, argv, sizeof(const char *) * argc);
+ argc = parse_options(argc, (const char **)__argv, record_options,
+ NULL, PARSE_OPT_STOP_AT_NON_OPTION);
+ free(__argv);
+
+ return argc != 0;
+}
+
int cmd_trace(int argc, const char **argv, const char *prefix __used)
{
struct perf_session *session;
@@ -663,21 +679,28 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
}

if (suffix) {
+ bool system_wide = false;
+ int j = 0;
+
script_path = get_script_path(argv[2], suffix);
if (!script_path) {
fprintf(stderr, "script not found\n");
return -1;
}

+ if (!strcmp(suffix, RECORD_SUFFIX))
+ system_wide = !have_cmd(argc - 2, &argv[2]);
+
__argv = malloc((argc + 1) * sizeof(const char *));
if (!__argv)
die("malloc");
- __argv[0] = "/bin/sh";
- __argv[1] = script_path;
+ __argv[j++] = "/bin/sh";
+ __argv[j++] = script_path;
+ if (system_wide)
+ __argv[j++] = "-a";
for (i = 3; i < argc; i++)
- __argv[i - 1] = argv[i];
- __argv[argc - 1] = NULL;
+ __argv[j++] = argv[i];
+ __argv[j++] = NULL;

execvp("/bin/sh", (char **)__argv);
free(__argv);
--
Tom Zanussi, Intel Open Source Technology Center

2010-11-10 05:25:46

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 0/7] perf trace command-line cleanup

Ingo,

Please pull from Tom's git tree, I'm traveling and can't do
further tests, but all seems cool improvements,

Thanks a lot,

- Arnaldo

Em Tue, Nov 09, 2010 at 03:18:15PM -0600, [email protected] escreveu:
> From: Tom Zanussi <[email protected]>
>
> There are currently some inconsistencies in perf trace command-line
> handling - for example, the system-wide param is hard-coded into the
> canned scripts, and the user doesn't have any option to avoid it.
> This patchset removes that limitation and cleans up some related
> complications introduced by live-mode. It also more clearly documents
> usage, and fixes up a couple other minor problems.
>
> This patchset can also be pulled from here:
>
> git://github.com/zanussi/linux-2.6.git perf-trace-updates
>
>
> Tom Zanussi (7):
> perf trace scripting: fix some small memory leaks and missing error
> checks
> perf trace scripting: remove system-wide param from shell scripts
> perf record: make the record options available outside perf record
> perf trace record: handle commands correctly
> perf trace: live-mode command-line cleanup
> perf trace: update Documentation with new perf trace variants
> perf trace: update usage
>
> tools/perf/Documentation/perf-trace.txt | 57 +++++-
> tools/perf/builtin-record.c | 10 +-
> tools/perf/builtin-trace.c | 209 ++++++++++++++------
> tools/perf/scripts/perl/bin/failed-syscalls-record | 2 +-
> tools/perf/scripts/perl/bin/rw-by-file-record | 2 +-
> tools/perf/scripts/perl/bin/rw-by-pid-record | 2 +-
> tools/perf/scripts/perl/bin/rwtop-record | 2 +-
> tools/perf/scripts/perl/bin/wakeup-latency-record | 2 +-
> tools/perf/scripts/perl/bin/workqueue-stats-record | 2 +-
> .../python/bin/failed-syscalls-by-pid-record | 2 +-
> .../scripts/python/bin/futex-contention-record | 2 +-
> tools/perf/scripts/python/bin/netdev-times-record | 2 +-
> .../perf/scripts/python/bin/sched-migration-record | 2 +-
> tools/perf/scripts/python/bin/sctop-record | 2 +-
> .../python/bin/syscall-counts-by-pid-record | 2 +-
> .../perf/scripts/python/bin/syscall-counts-record | 2 +-
> 16 files changed, 217 insertions(+), 85 deletions(-)
>
> --
> Tom Zanussi, Intel Open Source Technology Center

2010-11-10 07:32:47

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/7] perf trace command-line cleanup


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Ingo,
>
> Please pull from Tom's git tree, I'm traveling and can't do
> further tests, but all seems cool improvements,

I cannot pull it - the tree is based against tip:master, and the patches sent in
email wont apply.

Tom, mind rebasing your fixes to perf/urgent [which is really just Linus's latest
tree right now], with Arnaldo's Acked-by added to each patch?

Thanks,

Ingo

2010-11-10 18:09:53

by Tom Zanussi

[permalink] [raw]
Subject: Re: [PATCH 0/7] perf trace command-line cleanup

On Wed, 2010-11-10 at 08:32 +0100, Ingo Molnar wrote:
> * Arnaldo Carvalho de Melo <[email protected]> wrote:
>
> > Ingo,
> >
> > Please pull from Tom's git tree, I'm traveling and can't do
> > further tests, but all seems cool improvements,
>
> I cannot pull it - the tree is based against tip:master, and the patches sent in
> email wont apply.
>
> Tom, mind rebasing your fixes to perf/urgent [which is really just Linus's latest
> tree right now], with Arnaldo's Acked-by added to each patch?
>

Sure, coming up...

Tom