aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-07-05 05:28:13 -0400
committerIngo Molnar <mingo@kernel.org>2014-07-05 05:28:13 -0400
commit432100ba2aacc2146a2b1f26e5b5ae5d6e29972a (patch)
treede1bd7b51e55c8b61507a56d69e6e333b4c84cd7
parent2172c1f5aa58310784f358ca20fdddfcdc2a0d7b (diff)
parente281a9606d7073c517f2571e83faaff029ddc1cf (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New features: * Add support for pagefault tracing in 'trace', please see multiple examples in the changeset messages (Stanislav Fomichev). User visible changes: * Fallback to syscalls:* when raw_syscalls:* is not available in the perl and python perf scripts. (Daniel Bristot de Oliveira) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-trace.txt46
-rw-r--r--tools/perf/builtin-trace.c237
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record3
-rw-r--r--tools/perf/scripts/perl/failed-syscalls.pl5
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record3
-rw-r--r--tools/perf/scripts/python/bin/sctop-record3
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record3
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record3
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py5
-rw-r--r--tools/perf/scripts/python/sctop.py5
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py5
-rw-r--r--tools/perf/scripts/python/syscall-counts.py5
12 files changed, 280 insertions, 43 deletions
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index fae38d9a44a4..02aac831bdd9 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -107,6 +107,52 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
107 Show tool stats such as number of times fd->pathname was discovered thru 107 Show tool stats such as number of times fd->pathname was discovered thru
108 hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc. 108 hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc.
109 109
110-F=[all|min|maj]::
111--pf=[all|min|maj]::
112 Trace pagefaults. Optionally, you can specify whether you want minor,
113 major or all pagefaults. Default value is maj.
114
115--syscalls::
116 Trace system calls. This options is enabled by default.
117
118PAGEFAULTS
119----------
120
121When tracing pagefaults, the format of the trace is as follows:
122
123<min|maj>fault [<ip.symbol>+<ip.offset>] => <addr.dso@addr.offset> (<map type><addr level>).
124
125- min/maj indicates whether fault event is minor or major;
126- ip.symbol shows symbol for instruction pointer (the code that generated the
127 fault); if no debug symbols available, perf trace will print raw IP;
128- addr.dso shows DSO for the faulted address;
129- map type is either 'd' for non-executable maps or 'x' for executable maps;
130- addr level is either 'k' for kernel dso or '.' for user dso.
131
132For symbols resolution you may need to install debugging symbols.
133
134Please be aware that duration is currently always 0 and doesn't reflect actual
135time it took for fault to be handled!
136
137When --verbose specified, perf trace tries to print all available information
138for both IP and fault address in the form of dso@symbol+offset.
139
140EXAMPLES
141--------
142
143Trace only major pagefaults:
144
145 $ perf trace --no-syscalls -F
146
147Trace syscalls, major and minor pagefaults:
148
149 $ perf trace -F all
150
151 1416.547 ( 0.000 ms): python/20235 majfault [CRYPTO_push_info_+0x0] => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0@0x61be0 (x.)
152
153 As you can see, there was major pagefault in python process, from
154 CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so.
155
110SEE ALSO 156SEE ALSO
111-------- 157--------
112linkperf:perf-record[1], linkperf:perf-script[1] 158linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 5549cee61680..dc7a694b61fe 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1178,6 +1178,9 @@ fail:
1178 return NULL; 1178 return NULL;
1179} 1179}
1180 1180
1181#define TRACE_PFMAJ (1 << 0)
1182#define TRACE_PFMIN (1 << 1)
1183
1181struct trace { 1184struct trace {
1182 struct perf_tool tool; 1185 struct perf_tool tool;
1183 struct { 1186 struct {
@@ -1212,6 +1215,8 @@ struct trace {
1212 bool summary_only; 1215 bool summary_only;
1213 bool show_comm; 1216 bool show_comm;
1214 bool show_tool_stats; 1217 bool show_tool_stats;
1218 bool trace_syscalls;
1219 int trace_pgfaults;
1215}; 1220};
1216 1221
1217static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1222static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
@@ -1538,6 +1543,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1538} 1543}
1539 1544
1540typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel, 1545typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
1546 union perf_event *event,
1541 struct perf_sample *sample); 1547 struct perf_sample *sample);
1542 1548
1543static struct syscall *trace__syscall_info(struct trace *trace, 1549static struct syscall *trace__syscall_info(struct trace *trace,
@@ -1610,6 +1616,7 @@ static void thread__update_stats(struct thread_trace *ttrace,
1610} 1616}
1611 1617
1612static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1618static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1619 union perf_event *event __maybe_unused,
1613 struct perf_sample *sample) 1620 struct perf_sample *sample)
1614{ 1621{
1615 char *msg; 1622 char *msg;
@@ -1658,6 +1665,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1658} 1665}
1659 1666
1660static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1667static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1668 union perf_event *event __maybe_unused,
1661 struct perf_sample *sample) 1669 struct perf_sample *sample)
1662{ 1670{
1663 int ret; 1671 int ret;
@@ -1735,6 +1743,7 @@ out:
1735} 1743}
1736 1744
1737static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel, 1745static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1746 union perf_event *event __maybe_unused,
1738 struct perf_sample *sample) 1747 struct perf_sample *sample)
1739{ 1748{
1740 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname"); 1749 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
@@ -1742,6 +1751,7 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1742} 1751}
1743 1752
1744static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, 1753static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
1754 union perf_event *event __maybe_unused,
1745 struct perf_sample *sample) 1755 struct perf_sample *sample)
1746{ 1756{
1747 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 1757 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
@@ -1768,6 +1778,68 @@ out_dump:
1768 return 0; 1778 return 0;
1769} 1779}
1770 1780
1781static void print_location(FILE *f, struct perf_sample *sample,
1782 struct addr_location *al,
1783 bool print_dso, bool print_sym)
1784{
1785
1786 if ((verbose || print_dso) && al->map)
1787 fprintf(f, "%s@", al->map->dso->long_name);
1788
1789 if ((verbose || print_sym) && al->sym)
1790 fprintf(f, "%s+0x%lx", al->sym->name,
1791 al->addr - al->sym->start);
1792 else if (al->map)
1793 fprintf(f, "0x%lx", al->addr);
1794 else
1795 fprintf(f, "0x%lx", sample->addr);
1796}
1797
1798static int trace__pgfault(struct trace *trace,
1799 struct perf_evsel *evsel,
1800 union perf_event *event,
1801 struct perf_sample *sample)
1802{
1803 struct thread *thread;
1804 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1805 struct addr_location al;
1806 char map_type = 'd';
1807
1808 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1809
1810 thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION,
1811 sample->ip, &al);
1812
1813 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
1814
1815 fprintf(trace->output, "%sfault [",
1816 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
1817 "maj" : "min");
1818
1819 print_location(trace->output, sample, &al, false, true);
1820
1821 fprintf(trace->output, "] => ");
1822
1823 thread__find_addr_location(thread, trace->host, cpumode, MAP__VARIABLE,
1824 sample->addr, &al);
1825
1826 if (!al.map) {
1827 thread__find_addr_location(thread, trace->host, cpumode,
1828 MAP__FUNCTION, sample->addr, &al);
1829
1830 if (al.map)
1831 map_type = 'x';
1832 else
1833 map_type = '?';
1834 }
1835
1836 print_location(trace->output, sample, &al, true, false);
1837
1838 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1839
1840 return 0;
1841}
1842
1771static bool skip_sample(struct trace *trace, struct perf_sample *sample) 1843static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1772{ 1844{
1773 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) || 1845 if ((trace->pid_list && intlist__find(trace->pid_list, sample->pid)) ||
@@ -1781,7 +1853,7 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample)
1781} 1853}
1782 1854
1783static int trace__process_sample(struct perf_tool *tool, 1855static int trace__process_sample(struct perf_tool *tool,
1784 union perf_event *event __maybe_unused, 1856 union perf_event *event,
1785 struct perf_sample *sample, 1857 struct perf_sample *sample,
1786 struct perf_evsel *evsel, 1858 struct perf_evsel *evsel,
1787 struct machine *machine __maybe_unused) 1859 struct machine *machine __maybe_unused)
@@ -1799,7 +1871,7 @@ static int trace__process_sample(struct perf_tool *tool,
1799 1871
1800 if (handler) { 1872 if (handler) {
1801 ++trace->nr_events; 1873 ++trace->nr_events;
1802 handler(trace, evsel, sample); 1874 handler(trace, evsel, event, sample);
1803 } 1875 }
1804 1876
1805 return err; 1877 return err;
@@ -1826,7 +1898,7 @@ static int parse_target_str(struct trace *trace)
1826 return 0; 1898 return 0;
1827} 1899}
1828 1900
1829static int trace__record(int argc, const char **argv) 1901static int trace__record(struct trace *trace, int argc, const char **argv)
1830{ 1902{
1831 unsigned int rec_argc, i, j; 1903 unsigned int rec_argc, i, j;
1832 const char **rec_argv; 1904 const char **rec_argv;
@@ -1835,34 +1907,54 @@ static int trace__record(int argc, const char **argv)
1835 "-R", 1907 "-R",
1836 "-m", "1024", 1908 "-m", "1024",
1837 "-c", "1", 1909 "-c", "1",
1838 "-e",
1839 }; 1910 };
1840 1911
1912 const char * const sc_args[] = { "-e", };
1913 unsigned int sc_args_nr = ARRAY_SIZE(sc_args);
1914 const char * const majpf_args[] = { "-e", "major-faults" };
1915 unsigned int majpf_args_nr = ARRAY_SIZE(majpf_args);
1916 const char * const minpf_args[] = { "-e", "minor-faults" };
1917 unsigned int minpf_args_nr = ARRAY_SIZE(minpf_args);
1918
1841 /* +1 is for the event string below */ 1919 /* +1 is for the event string below */
1842 rec_argc = ARRAY_SIZE(record_args) + 1 + argc; 1920 rec_argc = ARRAY_SIZE(record_args) + sc_args_nr + 1 +
1921 majpf_args_nr + minpf_args_nr + argc;
1843 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1922 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1844 1923
1845 if (rec_argv == NULL) 1924 if (rec_argv == NULL)
1846 return -ENOMEM; 1925 return -ENOMEM;
1847 1926
1927 j = 0;
1848 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1928 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1849 rec_argv[i] = record_args[i]; 1929 rec_argv[j++] = record_args[i];
1850 1930
1851 /* event string may be different for older kernels - e.g., RHEL6 */ 1931 if (trace->trace_syscalls) {
1852 if (is_valid_tracepoint("raw_syscalls:sys_enter")) 1932 for (i = 0; i < sc_args_nr; i++)
1853 rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit"; 1933 rec_argv[j++] = sc_args[i];
1854 else if (is_valid_tracepoint("syscalls:sys_enter")) 1934
1855 rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit"; 1935 /* event string may be different for older kernels - e.g., RHEL6 */
1856 else { 1936 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
1857 pr_err("Neither raw_syscalls nor syscalls events exist.\n"); 1937 rec_argv[j++] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
1858 return -1; 1938 else if (is_valid_tracepoint("syscalls:sys_enter"))
1939 rec_argv[j++] = "syscalls:sys_enter,syscalls:sys_exit";
1940 else {
1941 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
1942 return -1;
1943 }
1859 } 1944 }
1860 i++;
1861 1945
1862 for (j = 0; j < (unsigned int)argc; j++, i++) 1946 if (trace->trace_pgfaults & TRACE_PFMAJ)
1863 rec_argv[i] = argv[j]; 1947 for (i = 0; i < majpf_args_nr; i++)
1948 rec_argv[j++] = majpf_args[i];
1949
1950 if (trace->trace_pgfaults & TRACE_PFMIN)
1951 for (i = 0; i < minpf_args_nr; i++)
1952 rec_argv[j++] = minpf_args[i];
1864 1953
1865 return cmd_record(i, rec_argv, NULL); 1954 for (i = 0; i < (unsigned int)argc; i++)
1955 rec_argv[j++] = argv[i];
1956
1957 return cmd_record(j, rec_argv, NULL);
1866} 1958}
1867 1959
1868static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); 1960static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
@@ -1882,6 +1974,30 @@ static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
1882 perf_evlist__add(evlist, evsel); 1974 perf_evlist__add(evlist, evsel);
1883} 1975}
1884 1976
1977static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
1978 u64 config)
1979{
1980 struct perf_evsel *evsel;
1981 struct perf_event_attr attr = {
1982 .type = PERF_TYPE_SOFTWARE,
1983 .mmap_data = 1,
1984 .sample_period = 1,
1985 };
1986
1987 attr.config = config;
1988
1989 event_attr_init(&attr);
1990
1991 evsel = perf_evsel__new(&attr);
1992 if (!evsel)
1993 return -ENOMEM;
1994
1995 evsel->handler = trace__pgfault;
1996 perf_evlist__add(evlist, evsel);
1997
1998 return 0;
1999}
2000
1885static int trace__run(struct trace *trace, int argc, const char **argv) 2001static int trace__run(struct trace *trace, int argc, const char **argv)
1886{ 2002{
1887 struct perf_evlist *evlist = perf_evlist__new(); 2003 struct perf_evlist *evlist = perf_evlist__new();
@@ -1897,10 +2013,21 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1897 goto out; 2013 goto out;
1898 } 2014 }
1899 2015
1900 if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit)) 2016 if (trace->trace_syscalls &&
2017 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2018 trace__sys_exit))
2019 goto out_error_tp;
2020
2021 if (trace->trace_syscalls)
2022 perf_evlist__add_vfs_getname(evlist);
2023
2024 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
2025 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ))
1901 goto out_error_tp; 2026 goto out_error_tp;
1902 2027
1903 perf_evlist__add_vfs_getname(evlist); 2028 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2029 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
2030 goto out_error_tp;
1904 2031
1905 if (trace->sched && 2032 if (trace->sched &&
1906 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2033 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -1982,7 +2109,8 @@ again:
1982 goto next_event; 2109 goto next_event;
1983 } 2110 }
1984 2111
1985 if (sample.raw_data == NULL) { 2112 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2113 sample.raw_data == NULL) {
1986 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 2114 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1987 perf_evsel__name(evsel), sample.tid, 2115 perf_evsel__name(evsel), sample.tid,
1988 sample.cpu, sample.raw_size); 2116 sample.cpu, sample.raw_size);
@@ -1990,7 +2118,7 @@ again:
1990 } 2118 }
1991 2119
1992 handler = evsel->handler; 2120 handler = evsel->handler;
1993 handler(trace, evsel, &sample); 2121 handler(trace, evsel, event, &sample);
1994next_event: 2122next_event:
1995 perf_evlist__mmap_consume(evlist, i); 2123 perf_evlist__mmap_consume(evlist, i);
1996 2124
@@ -2093,13 +2221,10 @@ static int trace__replay(struct trace *trace)
2093 if (evsel == NULL) 2221 if (evsel == NULL)
2094 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2222 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2095 "syscalls:sys_enter"); 2223 "syscalls:sys_enter");
2096 if (evsel == NULL) {
2097 pr_err("Data file does not have raw_syscalls:sys_enter event\n");
2098 goto out;
2099 }
2100 2224
2101 if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || 2225 if (evsel &&
2102 perf_evsel__init_sc_tp_ptr_field(evsel, args)) { 2226 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
2227 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
2103 pr_err("Error during initialize raw_syscalls:sys_enter event\n"); 2228 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2104 goto out; 2229 goto out;
2105 } 2230 }
@@ -2109,15 +2234,19 @@ static int trace__replay(struct trace *trace)
2109 if (evsel == NULL) 2234 if (evsel == NULL)
2110 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2235 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2111 "syscalls:sys_exit"); 2236 "syscalls:sys_exit");
2112 if (evsel == NULL) { 2237 if (evsel &&
2113 pr_err("Data file does not have raw_syscalls:sys_exit event\n"); 2238 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
2239 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
2240 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
2114 goto out; 2241 goto out;
2115 } 2242 }
2116 2243
2117 if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || 2244 evlist__for_each(session->evlist, evsel) {
2118 perf_evsel__init_sc_tp_uint_field(evsel, ret)) { 2245 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2119 pr_err("Error during initialize raw_syscalls:sys_exit event\n"); 2246 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2120 goto out; 2247 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
2248 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS))
2249 evsel->handler = trace__pgfault;
2121 } 2250 }
2122 2251
2123 err = parse_target_str(trace); 2252 err = parse_target_str(trace);
@@ -2264,6 +2393,23 @@ static int trace__open_output(struct trace *trace, const char *filename)
2264 return trace->output == NULL ? -errno : 0; 2393 return trace->output == NULL ? -errno : 0;
2265} 2394}
2266 2395
2396static int parse_pagefaults(const struct option *opt, const char *str,
2397 int unset __maybe_unused)
2398{
2399 int *trace_pgfaults = opt->value;
2400
2401 if (strcmp(str, "all") == 0)
2402 *trace_pgfaults |= TRACE_PFMAJ | TRACE_PFMIN;
2403 else if (strcmp(str, "maj") == 0)
2404 *trace_pgfaults |= TRACE_PFMAJ;
2405 else if (strcmp(str, "min") == 0)
2406 *trace_pgfaults |= TRACE_PFMIN;
2407 else
2408 return -1;
2409
2410 return 0;
2411}
2412
2267int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2413int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2268{ 2414{
2269 const char * const trace_usage[] = { 2415 const char * const trace_usage[] = {
@@ -2293,6 +2439,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2293 }, 2439 },
2294 .output = stdout, 2440 .output = stdout,
2295 .show_comm = true, 2441 .show_comm = true,
2442 .trace_syscalls = true,
2296 }; 2443 };
2297 const char *output_name = NULL; 2444 const char *output_name = NULL;
2298 const char *ev_qualifier_str = NULL; 2445 const char *ev_qualifier_str = NULL;
@@ -2330,20 +2477,34 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2330 "Show only syscall summary with statistics"), 2477 "Show only syscall summary with statistics"),
2331 OPT_BOOLEAN('S', "with-summary", &trace.summary, 2478 OPT_BOOLEAN('S', "with-summary", &trace.summary,
2332 "Show all syscalls and summary with statistics"), 2479 "Show all syscalls and summary with statistics"),
2480 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2481 "Trace pagefaults", parse_pagefaults, "maj"),
2482 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
2333 OPT_END() 2483 OPT_END()
2334 }; 2484 };
2335 int err; 2485 int err;
2336 char bf[BUFSIZ]; 2486 char bf[BUFSIZ];
2337 2487
2338 if ((argc > 1) && (strcmp(argv[1], "record") == 0)) 2488 argc = parse_options(argc, argv, trace_options, trace_usage,
2339 return trace__record(argc-2, &argv[2]); 2489 PARSE_OPT_STOP_AT_NON_OPTION);
2490
2491 if (trace.trace_pgfaults) {
2492 trace.opts.sample_address = true;
2493 trace.opts.sample_time = true;
2494 }
2340 2495
2341 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 2496 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2497 return trace__record(&trace, argc-1, &argv[1]);
2342 2498
2343 /* summary_only implies summary option, but don't overwrite summary if set */ 2499 /* summary_only implies summary option, but don't overwrite summary if set */
2344 if (trace.summary_only) 2500 if (trace.summary_only)
2345 trace.summary = trace.summary_only; 2501 trace.summary = trace.summary_only;
2346 2502
2503 if (!trace.trace_syscalls && !trace.trace_pgfaults) {
2504 pr_err("Please specify something to trace.\n");
2505 return -1;
2506 }
2507
2347 if (output_name != NULL) { 2508 if (output_name != NULL) {
2348 err = trace__open_output(&trace, output_name); 2509 err = trace__open_output(&trace, output_name);
2349 if (err < 0) { 2510 if (err < 0) {
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
index 8104895a7b67..74685f318379 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-record
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -1,2 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -e raw_syscalls:sys_exit $@ 2(perf record -e raw_syscalls:sys_exit $@ || \
3 perf record -e syscalls:sys_exit $@) 2> /dev/null
diff --git a/tools/perf/scripts/perl/failed-syscalls.pl b/tools/perf/scripts/perl/failed-syscalls.pl
index 94bc25a347eb..55e7ae4c5c88 100644
--- a/tools/perf/scripts/perl/failed-syscalls.pl
+++ b/tools/perf/scripts/perl/failed-syscalls.pl
@@ -26,6 +26,11 @@ sub raw_syscalls::sys_exit
26 } 26 }
27} 27}
28 28
29sub syscalls::sys_exit
30{
31 raw_syscalls::sys_exit(@_)
32}
33
29sub trace_end 34sub trace_end
30{ 35{
31 printf("\nfailed syscalls by comm:\n\n"); 36 printf("\nfailed syscalls by comm:\n\n");
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 8104895a7b67..74685f318379 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,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -e raw_syscalls:sys_exit $@ 2(perf record -e raw_syscalls:sys_exit $@ || \
3 perf record -e syscalls:sys_exit $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
index 4efbfaa7f6a5..d6940841e54f 100644
--- a/tools/perf/scripts/python/bin/sctop-record
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -1,2 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@ 2(perf record -e raw_syscalls:sys_enter $@ || \
3 perf record -e syscalls:sys_enter $@) 2> /dev/null
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 4efbfaa7f6a5..d6940841e54f 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,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@ 2(perf record -e raw_syscalls:sys_enter $@ || \
3 perf record -e syscalls:sys_enter $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
index 4efbfaa7f6a5..d6940841e54f 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -1,2 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@ 2(perf record -e raw_syscalls:sys_enter $@ || \
3 perf record -e syscalls:sys_enter $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 85805fac4116..266a8364bce5 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -50,6 +50,11 @@ def raw_syscalls__sys_exit(event_name, context, common_cpu,
50 except TypeError: 50 except TypeError:
51 syscalls[common_comm][common_pid][id][ret] = 1 51 syscalls[common_comm][common_pid][id][ret] = 1
52 52
53def syscalls__sys_exit(event_name, context, common_cpu,
54 common_secs, common_nsecs, common_pid, common_comm,
55 id, ret):
56 raw_syscalls__sys_exit(**locals())
57
53def print_error_totals(): 58def print_error_totals():
54 if for_comm is not None: 59 if for_comm is not None:
55 print "\nsyscall errors for %s:\n\n" % (for_comm), 60 print "\nsyscall errors for %s:\n\n" % (for_comm),
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 42c267e292fa..c9f3058b7dd4 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -53,6 +53,11 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
53 except TypeError: 53 except TypeError:
54 syscalls[id] = 1 54 syscalls[id] = 1
55 55
56def syscalls__sys_enter(event_name, context, common_cpu,
57 common_secs, common_nsecs, common_pid, common_comm,
58 id, args):
59 raw_syscalls__sys_enter(**locals())
60
56def print_syscall_totals(interval): 61def print_syscall_totals(interval):
57 while 1: 62 while 1:
58 clear_term() 63 clear_term()
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index c64d1c55d745..cf2054c529c9 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -48,6 +48,11 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
48 except TypeError: 48 except TypeError:
49 syscalls[common_comm][common_pid][id] = 1 49 syscalls[common_comm][common_pid][id] = 1
50 50
51def syscalls__sys_enter(event_name, context, common_cpu,
52 common_secs, common_nsecs, common_pid, common_comm,
53 id, args):
54 raw_syscalls__sys_enter(**locals())
55
51def print_syscall_totals(): 56def print_syscall_totals():
52 if for_comm is not None: 57 if for_comm is not None:
53 print "\nsyscall events for %s:\n\n" % (for_comm), 58 print "\nsyscall events for %s:\n\n" % (for_comm),
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index b435d3f188e8..92b29381bd39 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -44,6 +44,11 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
44 except TypeError: 44 except TypeError:
45 syscalls[id] = 1 45 syscalls[id] = 1
46 46
47def syscalls__sys_enter(event_name, context, common_cpu,
48 common_secs, common_nsecs, common_pid, common_comm,
49 id, args):
50 raw_syscalls__sys_enter(**locals())
51
47def print_syscall_totals(): 52def print_syscall_totals():
48 if for_comm is not None: 53 if for_comm is not None:
49 print "\nsyscall events for %s:\n\n" % (for_comm), 54 print "\nsyscall events for %s:\n\n" % (for_comm),