fluent-plugin-perf-tools 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +26 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +17 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/fluent-plugin-perf-tools.gemspec +48 -0
  14. data/lib/fluent/plugin/in_perf_tools.rb +42 -0
  15. data/lib/fluent/plugin/perf_tools/cachestat.rb +65 -0
  16. data/lib/fluent/plugin/perf_tools/command.rb +30 -0
  17. data/lib/fluent/plugin/perf_tools/version.rb +9 -0
  18. data/lib/fluent/plugin/perf_tools.rb +11 -0
  19. data/perf-tools/LICENSE +339 -0
  20. data/perf-tools/README.md +205 -0
  21. data/perf-tools/bin/bitesize +1 -0
  22. data/perf-tools/bin/cachestat +1 -0
  23. data/perf-tools/bin/execsnoop +1 -0
  24. data/perf-tools/bin/funccount +1 -0
  25. data/perf-tools/bin/funcgraph +1 -0
  26. data/perf-tools/bin/funcslower +1 -0
  27. data/perf-tools/bin/functrace +1 -0
  28. data/perf-tools/bin/iolatency +1 -0
  29. data/perf-tools/bin/iosnoop +1 -0
  30. data/perf-tools/bin/killsnoop +1 -0
  31. data/perf-tools/bin/kprobe +1 -0
  32. data/perf-tools/bin/opensnoop +1 -0
  33. data/perf-tools/bin/perf-stat-hist +1 -0
  34. data/perf-tools/bin/reset-ftrace +1 -0
  35. data/perf-tools/bin/syscount +1 -0
  36. data/perf-tools/bin/tcpretrans +1 -0
  37. data/perf-tools/bin/tpoint +1 -0
  38. data/perf-tools/bin/uprobe +1 -0
  39. data/perf-tools/deprecated/README.md +1 -0
  40. data/perf-tools/deprecated/execsnoop-proc +150 -0
  41. data/perf-tools/deprecated/execsnoop-proc.8 +80 -0
  42. data/perf-tools/deprecated/execsnoop-proc_example.txt +46 -0
  43. data/perf-tools/disk/bitesize +175 -0
  44. data/perf-tools/examples/bitesize_example.txt +63 -0
  45. data/perf-tools/examples/cachestat_example.txt +58 -0
  46. data/perf-tools/examples/execsnoop_example.txt +153 -0
  47. data/perf-tools/examples/funccount_example.txt +126 -0
  48. data/perf-tools/examples/funcgraph_example.txt +2178 -0
  49. data/perf-tools/examples/funcslower_example.txt +110 -0
  50. data/perf-tools/examples/functrace_example.txt +341 -0
  51. data/perf-tools/examples/iolatency_example.txt +350 -0
  52. data/perf-tools/examples/iosnoop_example.txt +302 -0
  53. data/perf-tools/examples/killsnoop_example.txt +62 -0
  54. data/perf-tools/examples/kprobe_example.txt +379 -0
  55. data/perf-tools/examples/opensnoop_example.txt +47 -0
  56. data/perf-tools/examples/perf-stat-hist_example.txt +149 -0
  57. data/perf-tools/examples/reset-ftrace_example.txt +88 -0
  58. data/perf-tools/examples/syscount_example.txt +297 -0
  59. data/perf-tools/examples/tcpretrans_example.txt +93 -0
  60. data/perf-tools/examples/tpoint_example.txt +210 -0
  61. data/perf-tools/examples/uprobe_example.txt +321 -0
  62. data/perf-tools/execsnoop +292 -0
  63. data/perf-tools/fs/cachestat +167 -0
  64. data/perf-tools/images/perf-tools_2016.png +0 -0
  65. data/perf-tools/iolatency +296 -0
  66. data/perf-tools/iosnoop +296 -0
  67. data/perf-tools/kernel/funccount +146 -0
  68. data/perf-tools/kernel/funcgraph +259 -0
  69. data/perf-tools/kernel/funcslower +248 -0
  70. data/perf-tools/kernel/functrace +192 -0
  71. data/perf-tools/kernel/kprobe +270 -0
  72. data/perf-tools/killsnoop +263 -0
  73. data/perf-tools/man/man8/bitesize.8 +70 -0
  74. data/perf-tools/man/man8/cachestat.8 +111 -0
  75. data/perf-tools/man/man8/execsnoop.8 +104 -0
  76. data/perf-tools/man/man8/funccount.8 +76 -0
  77. data/perf-tools/man/man8/funcgraph.8 +166 -0
  78. data/perf-tools/man/man8/funcslower.8 +129 -0
  79. data/perf-tools/man/man8/functrace.8 +123 -0
  80. data/perf-tools/man/man8/iolatency.8 +116 -0
  81. data/perf-tools/man/man8/iosnoop.8 +169 -0
  82. data/perf-tools/man/man8/killsnoop.8 +100 -0
  83. data/perf-tools/man/man8/kprobe.8 +162 -0
  84. data/perf-tools/man/man8/opensnoop.8 +113 -0
  85. data/perf-tools/man/man8/perf-stat-hist.8 +111 -0
  86. data/perf-tools/man/man8/reset-ftrace.8 +49 -0
  87. data/perf-tools/man/man8/syscount.8 +96 -0
  88. data/perf-tools/man/man8/tcpretrans.8 +93 -0
  89. data/perf-tools/man/man8/tpoint.8 +140 -0
  90. data/perf-tools/man/man8/uprobe.8 +168 -0
  91. data/perf-tools/misc/perf-stat-hist +223 -0
  92. data/perf-tools/net/tcpretrans +311 -0
  93. data/perf-tools/opensnoop +280 -0
  94. data/perf-tools/syscount +192 -0
  95. data/perf-tools/system/tpoint +232 -0
  96. data/perf-tools/tools/reset-ftrace +123 -0
  97. data/perf-tools/user/uprobe +390 -0
  98. metadata +349 -0
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/perl
2
+ #
3
+ # tcpretrans - show TCP retransmts, with address and other details.
4
+ # Written using Linux ftrace.
5
+ #
6
+ # This traces TCP retransmits, showing address, port, and TCP state information,
7
+ # and sometimes the PID (although usually not, since retransmits are usually
8
+ # sent by the kernel on timeouts). To keep overhead low, only
9
+ # tcp_retransmit_skb() calls are traced (this does not trace every packet).
10
+ #
11
+ # USAGE: ./tcpretrans [-hls]
12
+ #
13
+ # REQUIREMENTS: FTRACE and KPROBE CONFIG, tcp_retransmit_skb() kernel function,
14
+ # and tcp_send_loss_probe() when -l is used. You may have these already have
15
+ # these on recent kernels. And Perl.
16
+ #
17
+ # This was written as a proof of concept for ftrace, for older Linux systems,
18
+ # and without kernel debuginfo. It uses dynamic tracing of tcp_retransmit_skb(),
19
+ # and reads /proc/net/tcp for socket details. Its use of dynamic tracing and
20
+ # CPU registers is an unstable platform-specific workaround, and may require
21
+ # modifications to work on different kernels and platforms. This would be better
22
+ # written using a tracer such as SystemTap, and will likely be rewritten in the
23
+ # future when certain tracing features are added to the Linux kernel.
24
+ #
25
+ # When -l is used, this also uses dynamic tracing of tcp_send_loss_probe() and
26
+ # a register.
27
+ #
28
+ # Currently only IPv4 is supported, on x86_64. If you try this on a different
29
+ # architecture, you'll likely need to adjust the register locations (search
30
+ # for %di).
31
+ #
32
+ # OVERHEAD: The CPU overhead is relative to the rate of TCP retransmits, and is
33
+ # designed to be low as this does not examine every packet. Once per second the
34
+ # /proc/net/tcp file is read, and a buffer of retransmit trace events is
35
+ # retrieved from the kernel and processed.
36
+ #
37
+ # From perf-tools: https://github.com/brendangregg/perf-tools
38
+ #
39
+ # See the tcpretrans(8) man page (in perf-tools) for more info.
40
+ #
41
+ # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
42
+ #
43
+ # This program is free software; you can redistribute it and/or
44
+ # modify it under the terms of the GNU General Public License
45
+ # as published by the Free Software Foundation; either version 2
46
+ # of the License, or (at your option) any later version.
47
+ #
48
+ # This program is distributed in the hope that it will be useful,
49
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
50
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51
+ # GNU General Public License for more details.
52
+ #
53
+ # You should have received a copy of the GNU General Public License
54
+ # along with this program; if not, write to the Free Software Foundation,
55
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
56
+ #
57
+ # (http://www.gnu.org/copyleft/gpl.html)
58
+ #
59
+ # 28-Jul-2014 Brendan Gregg Created this.
60
+
61
+ use strict;
62
+ use warnings;
63
+ use POSIX qw(strftime);
64
+ use Getopt::Long;
65
+ my $tracing = "/sys/kernel/debug/tracing";
66
+ my $flock = "/var/tmp/.ftrace-lock";
67
+ my $interval = 1;
68
+ local $SIG{INT} = \&cleanup;
69
+ local $SIG{QUIT} = \&cleanup;
70
+ local $SIG{TERM} = \&cleanup;
71
+ local $SIG{PIPE} = \&cleanup;
72
+ local $SIG{HUP} = \&cleanup;
73
+ $| = 1;
74
+
75
+ ### options
76
+ my ($help, $stacks, $tlp);
77
+ GetOptions("help|h" => \$help,
78
+ "stacks|s" => \$stacks,
79
+ "tlp|l" => \$tlp)
80
+ or usage();
81
+ usage() if $help;
82
+
83
+ sub usage {
84
+ print STDERR "USAGE: tcpretrans [-hls]\n";
85
+ print STDERR " -h # help message\n";
86
+ print STDERR " -l # trace TCP tail loss probes\n";
87
+ print STDERR " -s # print stack traces\n";
88
+ print STDERR " eg,\n";
89
+ print STDERR " tcpretrans # trace TCP retransmits\n";
90
+ exit;
91
+ }
92
+
93
+ # delete lock and die
94
+ sub ldie {
95
+ unlink $flock;
96
+ die @_;
97
+ }
98
+
99
+ # end tracing (silently) and die
100
+ sub edie {
101
+ print STDERR "@_\n";
102
+ close STDOUT;
103
+ close STDERR;
104
+ cleanup();
105
+ }
106
+
107
+ sub writeto {
108
+ my ($string, $file) = @_;
109
+ open FILE, ">$file" or return 0;
110
+ print FILE $string or return 0;
111
+ close FILE or return 0;
112
+ }
113
+
114
+ sub appendto {
115
+ my ($string, $file) = @_;
116
+ open FILE, ">>$file" or return 0;
117
+ print FILE $string or return 0;
118
+ close FILE or return 0;
119
+ }
120
+
121
+ # kprobe functions
122
+ sub create_kprobe {
123
+ my ($kname, $kval) = @_;
124
+ appendto "p:$kname $kval", "kprobe_events" or return 0;
125
+ }
126
+
127
+ sub enable_kprobe {
128
+ my ($kname) = @_;
129
+ writeto "1", "events/kprobes/$kname/enable" or return 0;
130
+ }
131
+
132
+ sub remove_kprobe {
133
+ my ($kname) = @_;
134
+ writeto "0", "events/kprobes/$kname/enable" or return 0;
135
+ appendto "-:$kname", "kprobe_events" or return 0;
136
+ }
137
+
138
+ # tcp socket cache
139
+ my %tcp;
140
+ sub cache_tcp {
141
+ undef %tcp;
142
+ open(TCP, "/proc/net/tcp") or ldie "ERROR: reading /proc/net/tcp.";
143
+ while (<TCP>) {
144
+ next if /^ *sl/;
145
+ my ($sl, $local_address, $rem_address, $st, $tx_rx, $tr_tm,
146
+ $retrnsmt, $uid, $timeout, $inode, $jf, $sk) = split;
147
+ $sk =~ s/^0x//;
148
+ $tcp{$sk}{laddr} = $local_address;
149
+ $tcp{$sk}{raddr} = $rem_address;
150
+ $tcp{$sk}{state} = $st;
151
+ }
152
+ close TCP;
153
+ }
154
+
155
+ my @tcpstate;
156
+ sub map_tcp_states {
157
+ push @tcpstate, "NULL";
158
+ for (<DATA>) {
159
+ chomp;
160
+ s/.*TCP_//;
161
+ s/[, ].*$//;
162
+ push @tcpstate, $_;
163
+ }
164
+ }
165
+
166
+ # /proc/net/tcp hex addr to dotted quad decimal
167
+ sub inet_h2a {
168
+ my ($haddr) = @_;
169
+
170
+ my @addr = ();
171
+ for my $num ($haddr =~ /(..)(..)(..)(..)/) {
172
+ unshift @addr, hex($num);
173
+ }
174
+ return join(".", @addr);
175
+ }
176
+
177
+ ### check permissions
178
+ chdir "$tracing" or die "ERROR: accessing tracing. Root? Kernel has FTRACE?" .
179
+ "\ndebugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)";
180
+
181
+ ### ftrace lock
182
+ if (-e $flock) {
183
+ open FLOCK, $flock; my $fpid = <FLOCK>; chomp $fpid; close FLOCK;
184
+ die "ERROR: ftrace may be in use by PID $fpid ($flock)";
185
+ }
186
+ writeto "$$", $flock or die "ERROR: unable to write $flock.";
187
+
188
+ #
189
+ # Setup and begin tracing.
190
+ # Use of ldie() and edie() ensures that if an error is encountered, the
191
+ # kernel is not left in a partially configured state.
192
+ #
193
+ writeto "nop", "current_tracer" or ldie "ERROR: disabling current_tracer.";
194
+ my $kname_rtr = "tcpretrans_tcp_retransmit_skb";
195
+ my $kname_tlp = "tcpretrans_tcp_send_loss_probe";
196
+ create_kprobe $kname_rtr, "tcp_retransmit_skb sk=%di" or
197
+ ldie "ERROR: creating kprobe for tcp_retransmit_skb().";;
198
+ if ($tlp) {
199
+ create_kprobe $kname_tlp, "tcp_send_loss_probe sk=%di" or
200
+ edie "ERROR: creating kprobe for tcp_send_loss_probe(). " .
201
+ "Older kernel version?";
202
+ }
203
+ if ($stacks) {
204
+ writeto "1", "options/stacktrace" or print STDERR "WARNING: " .
205
+ "unable to enable stacktraces.\n";
206
+ }
207
+ enable_kprobe $kname_rtr or edie "ERROR: enabling $kname_rtr probe.";
208
+ if ($tlp) {
209
+ enable_kprobe $kname_tlp or edie "ERROR: enabling $kname_tlp probe.";
210
+ }
211
+ map_tcp_states();
212
+ printf "%-8s %-6s %-20s -- %-20s %-12s\n", "TIME", "PID", "LADDR:LPORT",
213
+ "RADDR:RPORT", "STATE";
214
+
215
+ #
216
+ # Read and print event data. This loop waits one second then reads the buffered
217
+ # trace data, then caches /proc/net/tcp, then iterates over the buffered trace
218
+ # data using the cached state. While this minimizes CPU overheads, it only
219
+ # works because sockets that are retransmitting are usually long lived, and
220
+ # remain in /proc/net/tcp for at least our sleep interval.
221
+ #
222
+ while (1) {
223
+ sleep $interval;
224
+
225
+ # buffer trace data
226
+ open TPIPE, "trace" or edie "ERROR: opening trace_pipe.";
227
+ my @trace = ();
228
+ while (<TPIPE>) {
229
+ next if /^#/;
230
+ push @trace, $_;
231
+ }
232
+ close TPIPE;
233
+ writeto "0", "trace" or edie "ERROR: clearing trace";
234
+
235
+ # cache /proc/net/tcp state
236
+ if (scalar @trace) {
237
+ cache_tcp();
238
+ }
239
+
240
+ # process and print events
241
+ for (@trace) {
242
+ if ($stacks && /^ *=>/) {
243
+ print $_;
244
+ next;
245
+ }
246
+
247
+ my ($taskpid, $rest) = split ' ', $_, 2;
248
+ my ($task, $pid) = $taskpid =~ /(.*)-(\d+)/;
249
+
250
+ my ($skp) = $rest =~ /sk=([0-9a-fx]*)/;
251
+ next unless defined $skp and $skp ne "";
252
+ $skp =~ s/^0x//;
253
+
254
+ my ($laddr, $lport, $raddr, $rport, $state);
255
+ if (defined $tcp{$skp}) {
256
+ # convert /proc/net/tcp hex to dotted quads
257
+ my ($hladdr, $hlport) = split /:/, $tcp{$skp}{laddr};
258
+ my ($hraddr, $hrport) = split /:/, $tcp{$skp}{raddr};
259
+ $laddr = inet_h2a($hladdr);
260
+ $raddr = inet_h2a($hraddr);
261
+ $lport = hex($hlport);
262
+ $rport = hex($hrport);
263
+ $state = $tcpstate[hex($tcp{$skp}{state})];
264
+ } else {
265
+ # socket closed too quickly
266
+ ($laddr, $raddr) = ("-", "-");
267
+ ($lport, $rport) = ("-", "-");
268
+ $state = "-";
269
+ }
270
+
271
+ my $now = strftime "%H:%M:%S", localtime;
272
+ printf "%-8s %-6s %-20s %s> %-20s %-12s\n", $now, $pid,
273
+ "$laddr:$lport", $rest =~ /$kname_tlp/ ? "L" : "R",
274
+ "$raddr:$rport", $state,
275
+ }
276
+ }
277
+
278
+ ### end tracing
279
+ cleanup();
280
+
281
+ sub cleanup {
282
+ print "\nEnding tracing...\n";
283
+ close TPIPE;
284
+ if ($stacks) {
285
+ writeto "0", "options/stacktrace" or print STDERR "WARNING: " .
286
+ "unable to disable stacktraces.\n";
287
+ }
288
+ remove_kprobe $kname_rtr
289
+ or print STDERR "ERROR: removing kprobe $kname_rtr\n";
290
+ if ($tlp) {
291
+ remove_kprobe $kname_tlp
292
+ or print STDERR "ERROR: removing kprobe $kname_tlp\n";
293
+ }
294
+ writeto "", "trace";
295
+ unlink $flock;
296
+ exit;
297
+ }
298
+
299
+ # from /usr/include/netinet/tcp.h:
300
+ __DATA__
301
+ TCP_ESTABLISHED = 1,
302
+ TCP_SYN_SENT,
303
+ TCP_SYN_RECV,
304
+ TCP_FIN_WAIT1,
305
+ TCP_FIN_WAIT2,
306
+ TCP_TIME_WAIT,
307
+ TCP_CLOSE,
308
+ TCP_CLOSE_WAIT,
309
+ TCP_LAST_ACK,
310
+ TCP_LISTEN,
311
+ TCP_CLOSING /* now a valid state */
@@ -0,0 +1,280 @@
1
+ #!/bin/bash
2
+ #
3
+ # opensnoop - trace open() syscalls with file details.
4
+ # Written using Linux ftrace.
5
+ #
6
+ # This traces open() syscalls, showing the file name and returned file
7
+ # descriptor number (or -1, for error).
8
+ #
9
+ # This implementation is designed to work on older kernel versions, and without
10
+ # kernel debuginfo. It works by dynamic tracing of the return value of getname()
11
+ # as a string, and associating it with the following open() syscall return.
12
+ # This approach is kernel version specific, and may not work on your version.
13
+ # It is a workaround, and proof of concept for ftrace, until more kernel tracing
14
+ # functionality is available.
15
+ #
16
+ # USAGE: ./opensnoop [-htx] [-d secs] [-p pid] [-L tid] [-n name] [filename]
17
+ #
18
+ # Run "opensnoop -h" for full usage.
19
+ #
20
+ # REQUIREMENTS: FTRACE and KPROBE CONFIG, syscalls:sys_exit_open tracepoint,
21
+ # getname() kernel function (you may already have these on recent kernels),
22
+ # and awk.
23
+ #
24
+ # From perf-tools: https://github.com/brendangregg/perf-tools
25
+ #
26
+ # See the opensnoop(8) man page (in perf-tools) for more info.
27
+ #
28
+ # COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
29
+ #
30
+ # This program is free software; you can redistribute it and/or
31
+ # modify it under the terms of the GNU General Public License
32
+ # as published by the Free Software Foundation; either version 2
33
+ # of the License, or (at your option) any later version.
34
+ #
35
+ # This program is distributed in the hope that it will be useful,
36
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
37
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
+ # GNU General Public License for more details.
39
+ #
40
+ # You should have received a copy of the GNU General Public License
41
+ # along with this program; if not, write to the Free Software Foundation,
42
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43
+ #
44
+ # (http://www.gnu.org/copyleft/gpl.html)
45
+ #
46
+ # 20-Jul-2014 Brendan Gregg Created this.
47
+
48
+ ### default variables
49
+ tracing=/sys/kernel/debug/tracing
50
+ flock=/var/tmp/.ftrace-lock; wroteflock=0
51
+ opt_duration=0; duration=; opt_name=0; name=; opt_pid=0; pid=; opt_tid=0; tid=
52
+ ftext=; opt_time=0; opt_fail=0; opt_file=0; file=
53
+ trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
54
+
55
+ function usage {
56
+ cat <<-END >&2
57
+ USAGE: opensnoop [-htx] [-d secs] [-p PID] [-L TID] [-n name] [filename]
58
+ -d seconds # trace duration, and use buffers
59
+ -n name # process name to match on open
60
+ -p PID # PID to match on open
61
+ -L TID # PID to match on open
62
+ -t # include time (seconds)
63
+ -x # only show failed opens
64
+ -h # this usage message
65
+ filename # match filename (partials, REs, ok)
66
+ eg,
67
+ opensnoop # watch open()s live (unbuffered)
68
+ opensnoop -d 1 # trace 1 sec (buffered)
69
+ opensnoop -p 181 # trace I/O issued by PID 181 only
70
+ opensnoop conf # trace filenames containing "conf"
71
+ opensnoop 'log$' # filenames ending in "log"
72
+
73
+ See the man page and example file for more info.
74
+ END
75
+ exit
76
+ }
77
+
78
+ function warn {
79
+ if ! eval "$@"; then
80
+ echo >&2 "WARNING: command failed \"$@\""
81
+ fi
82
+ }
83
+
84
+ function end {
85
+ # disable tracing
86
+ echo 2>/dev/null
87
+ echo "Ending tracing..." 2>/dev/null
88
+ cd $tracing
89
+ warn "echo 0 > events/kprobes/getnameprobe/enable"
90
+ warn "echo 0 > events/syscalls/sys_exit_open/enable"
91
+ warn "echo 0 > events/syscalls/sys_exit_openat/enable"
92
+ if (( opt_pid || opt_tid )); then
93
+ warn "echo 0 > events/kprobes/getnameprobe/filter"
94
+ warn "echo 0 > events/syscalls/sys_exit_open/filter"
95
+ warn "echo 0 > events/syscalls/sys_exit_openat/filter"
96
+ fi
97
+ warn "echo -:getnameprobe >> kprobe_events"
98
+ warn "echo > trace"
99
+ (( wroteflock )) && warn "rm $flock"
100
+ }
101
+
102
+ function die {
103
+ echo >&2 "$@"
104
+ exit 1
105
+ }
106
+
107
+ function edie {
108
+ # die with a quiet end()
109
+ echo >&2 "$@"
110
+ exec >/dev/null 2>&1
111
+ end
112
+ exit 1
113
+ }
114
+
115
+ ### process options
116
+ while getopts d:hn:p:L:tx opt
117
+ do
118
+ case $opt in
119
+ d) opt_duration=1; duration=$OPTARG ;;
120
+ n) opt_name=1; name=$OPTARG ;;
121
+ p) opt_pid=1; pid=$OPTARG ;;
122
+ L) opt_tid=1; tid=$OPTARG ;;
123
+ t) opt_time=1 ;;
124
+ x) opt_fail=1 ;;
125
+ h|?) usage ;;
126
+ esac
127
+ done
128
+ shift $(( $OPTIND - 1 ))
129
+ if (( $# )); then
130
+ opt_file=1
131
+ file=$1
132
+ shift
133
+ fi
134
+ (( $# )) && usage
135
+
136
+ ### option logic
137
+ (( opt_pid + opt_name + opt_tid > 1 )) && \
138
+ die "ERROR: use at most one of -p, -n, -L."
139
+ (( opt_pid )) && ftext=" issued by PID $pid"
140
+ (( opt_tid )) && ftext=" issued by TID $tid"
141
+ (( opt_name )) && ftext=" issued by process name \"$name\""
142
+ (( opt_file )) && ftext="$ftext for filenames containing \"$file\""
143
+ if (( opt_duration )); then
144
+ echo "Tracing open()s$ftext for $duration seconds (buffered)..."
145
+ else
146
+ echo "Tracing open()s$ftext. Ctrl-C to end."
147
+ fi
148
+
149
+ ### select awk
150
+ (( opt_duration )) && use=mawk || use=gawk # workaround for mawk fflush()
151
+ [[ -x /usr/bin/$use ]] && awk=$use || awk=awk
152
+
153
+ ### check permissions
154
+ cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
155
+ debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
156
+
157
+ ### ftrace lock
158
+ [[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
159
+ echo $$ > $flock || die "ERROR: unable to write $flock."
160
+ wroteflock=1
161
+
162
+ ### setup and begin tracing
163
+ echo nop > current_tracer
164
+ ver=$(uname -r)
165
+ if [[ "$ver" == 2.* || "$ver" == 3.[1-6].* ]]; then
166
+ # rval is char *
167
+ kprobe='r:getnameprobe getname +0($retval):string'
168
+ else
169
+ # rval is struct filename *
170
+ kprobe='r:getnameprobe getname +0(+0($retval)):string'
171
+ fi
172
+ if ! echo $kprobe >> kprobe_events; then
173
+ edie "ERROR: adding a kprobe for getname(). Exiting."
174
+ fi
175
+ if (( opt_pid )); then
176
+ filter=
177
+ for tid in /proc/$pid/task/*; do
178
+ filter="$filter || common_pid == ${tid##*/}"
179
+ done
180
+ filter=${filter:3} # trim leading ' || ' (four characters)
181
+ if ! echo $filter > events/kprobes/getnameprobe/filter || \
182
+ ! echo $filter > events/syscalls/sys_exit_open/filter || \
183
+ ! echo $filter > events/syscalls/sys_exit_openat/filter
184
+ then
185
+ edie "ERROR: setting -p $pid. Exiting."
186
+ fi
187
+ fi
188
+ if (( opt_tid )); then
189
+ if ! echo "common_pid == $tid" > events/kprobes/getnameprobe/filter || \
190
+ ! echo "common_pid == $tid" > events/syscalls/sys_exit_open/filter || \
191
+ ! echo "common_pid == $tid" > events/syscalls/sys_exit_openat/filter
192
+ then
193
+ edie "ERROR: setting -L $tid. Exiting."
194
+ fi
195
+ fi
196
+ if ! echo 1 > events/kprobes/getnameprobe/enable; then
197
+ edie "ERROR: enabling kprobe for getname(). Exiting."
198
+ fi
199
+ if ! echo 1 > events/syscalls/sys_exit_open/enable; then
200
+ edie "ERROR: enabling open() exit tracepoint. Exiting."
201
+ fi
202
+ if ! echo 1 > events/syscalls/sys_exit_openat/enable; then
203
+ edie "ERROR: enabling openat() exit tracepoint. Exiting."
204
+ fi
205
+ (( opt_time )) && printf "%-16s " "TIMEs"
206
+ printf "%-16.16s %-6s %4s %s\n" "COMM" "PID" "FD" "FILE"
207
+
208
+ #
209
+ # Determine output format. It may be one of the following (newest first):
210
+ # TASK-PID CPU# |||| TIMESTAMP FUNCTION
211
+ # TASK-PID CPU# TIMESTAMP FUNCTION
212
+ # To differentiate between them, the number of header fields is counted,
213
+ # and an offset set, to skip the extra column when needed.
214
+ #
215
+ offset=$($awk 'BEGIN { o = 0; }
216
+ $1 == "#" && $2 ~ /TASK/ && NF == 6 { o = 1; }
217
+ $2 ~ /TASK/ { print o; exit }' trace)
218
+
219
+ ### print trace buffer
220
+ warn "echo > trace"
221
+ ( if (( opt_duration )); then
222
+ # wait then dump buffer
223
+ sleep $duration
224
+ cat trace
225
+ else
226
+ # print buffer live
227
+ cat trace_pipe
228
+ fi ) | $awk -v o=$offset -v opt_name=$opt_name -v name=$name \
229
+ -v opt_duration=$opt_duration -v opt_time=$opt_time -v opt_fail=$opt_fail \
230
+ -v opt_file=$opt_file -v file=$file '
231
+ # common fields
232
+ $1 != "#" {
233
+ # task name can contain dashes and space
234
+ split($0, line, "-")
235
+ sub(/^[ \t\r\n]+/, "", line[1])
236
+ comm = line[1]
237
+ if (opt_name && match(comm, name) == 0)
238
+ next
239
+ sub(/ .*$/, "", line[2])
240
+ pid = line[2]
241
+ }
242
+
243
+ # do_sys_open()
244
+ $1 != "#" && $(5+o) ~ /do_sys_open/ {
245
+ #
246
+ # eg: ... (do_sys_open+0xc3/0x220 <- getname) arg1="file1"
247
+ #
248
+ match($0, /arg1=\"(.+)\"/, m)
249
+ lastfile[pid] = m[1]
250
+ }
251
+
252
+ # sys_open() / sys_openat()
253
+ $1 != "#" && ($(4+o) == "sys_open" || $(4+o) == "sys_openat") {
254
+ filename = lastfile[pid]
255
+ if (!filename)
256
+ next
257
+ delete lastfile[pid]
258
+ if (opt_file && filename !~ file)
259
+ next
260
+ rval = $NF
261
+ # matched failed as beginning with 0xfffff
262
+ if (opt_fail && rval !~ /0xfffff/)
263
+ next
264
+ if (rval ~ /0xfffff/)
265
+ rval = -1
266
+
267
+ if (opt_time) {
268
+ time = $(3+o); sub(":", "", time)
269
+ printf "%-16s ", time
270
+ }
271
+ printf "%-16.16s %-6s %4s %s\n", comm, pid, rval, filename
272
+ }
273
+
274
+ $0 ~ /LOST.*EVENTS/ {
275
+ delete lastfile
276
+ print "WARNING: " $0 > "/dev/stderr" }
277
+ '
278
+
279
+ ### end tracing
280
+ end