1 #!/usr/bin/perl -w 1 #!/usr/bin/perl -w 2 # SPDX-License-Identifier: GPL-2.0-only 2 # SPDX-License-Identifier: GPL-2.0-only 3 # (c) 2010, Tom Zanussi <tzanussi@gmail.com> 3 # (c) 2010, Tom Zanussi <tzanussi@gmail.com> 4 4 5 # read/write top 5 # read/write top 6 # 6 # 7 # Periodically displays system-wide r/w call a 7 # Periodically displays system-wide r/w call activity, broken down by 8 # pid. If an [interval] arg is specified, the 8 # pid. If an [interval] arg is specified, the display will be 9 # refreshed every [interval] seconds. The def 9 # refreshed every [interval] seconds. The default interval is 3 10 # seconds. 10 # seconds. 11 11 12 use 5.010000; 12 use 5.010000; 13 use strict; 13 use strict; 14 use warnings; 14 use warnings; 15 15 16 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/P 16 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; 17 use lib "./Perf-Trace-Util/lib"; 17 use lib "./Perf-Trace-Util/lib"; 18 use Perf::Trace::Core; 18 use Perf::Trace::Core; 19 use Perf::Trace::Util; 19 use Perf::Trace::Util; 20 use POSIX qw/SIGALRM SA_RESTART/; 20 use POSIX qw/SIGALRM SA_RESTART/; 21 21 22 my $default_interval = 3; 22 my $default_interval = 3; 23 my $nlines = 20; 23 my $nlines = 20; 24 my $print_thread; 24 my $print_thread; 25 my $print_pending = 0; 25 my $print_pending = 0; 26 26 27 my %reads; 27 my %reads; 28 my %writes; 28 my %writes; 29 29 30 my $interval = shift; 30 my $interval = shift; 31 if (!$interval) { 31 if (!$interval) { 32 $interval = $default_interval; 32 $interval = $default_interval; 33 } 33 } 34 34 35 sub syscalls::sys_exit_read 35 sub syscalls::sys_exit_read 36 { 36 { 37 my ($event_name, $context, $common_cpu, $c 37 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 38 $common_pid, $common_comm, $common_cal 38 $common_pid, $common_comm, $common_callchain, 39 $nr, $ret) = @_; 39 $nr, $ret) = @_; 40 40 41 print_check(); 41 print_check(); 42 42 43 if ($ret > 0) { 43 if ($ret > 0) { 44 $reads{$common_pid}{bytes_read} += $re 44 $reads{$common_pid}{bytes_read} += $ret; 45 } else { 45 } else { 46 if (!defined ($reads{$common_pid}{byte 46 if (!defined ($reads{$common_pid}{bytes_read})) { 47 $reads{$common_pid}{bytes_read} = 47 $reads{$common_pid}{bytes_read} = 0; 48 } 48 } 49 $reads{$common_pid}{errors}{$ret}++; 49 $reads{$common_pid}{errors}{$ret}++; 50 } 50 } 51 } 51 } 52 52 53 sub syscalls::sys_enter_read 53 sub syscalls::sys_enter_read 54 { 54 { 55 my ($event_name, $context, $common_cpu, $c 55 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 56 $common_pid, $common_comm, $common_cal 56 $common_pid, $common_comm, $common_callchain, 57 $nr, $fd, $buf, $count) = @_; 57 $nr, $fd, $buf, $count) = @_; 58 58 59 print_check(); 59 print_check(); 60 60 61 $reads{$common_pid}{bytes_requested} += $c 61 $reads{$common_pid}{bytes_requested} += $count; 62 $reads{$common_pid}{total_reads}++; 62 $reads{$common_pid}{total_reads}++; 63 $reads{$common_pid}{comm} = $common_comm; 63 $reads{$common_pid}{comm} = $common_comm; 64 } 64 } 65 65 66 sub syscalls::sys_exit_write 66 sub syscalls::sys_exit_write 67 { 67 { 68 my ($event_name, $context, $common_cpu, $c 68 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 69 $common_pid, $common_comm, $common_cal 69 $common_pid, $common_comm, $common_callchain, 70 $nr, $ret) = @_; 70 $nr, $ret) = @_; 71 71 72 print_check(); 72 print_check(); 73 73 74 if ($ret <= 0) { 74 if ($ret <= 0) { 75 $writes{$common_pid}{errors}{$ret}++; 75 $writes{$common_pid}{errors}{$ret}++; 76 } 76 } 77 } 77 } 78 78 79 sub syscalls::sys_enter_write 79 sub syscalls::sys_enter_write 80 { 80 { 81 my ($event_name, $context, $common_cpu, $c 81 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 82 $common_pid, $common_comm, $common_cal 82 $common_pid, $common_comm, $common_callchain, 83 $nr, $fd, $buf, $count) = @_; 83 $nr, $fd, $buf, $count) = @_; 84 84 85 print_check(); 85 print_check(); 86 86 87 $writes{$common_pid}{bytes_written} += $co 87 $writes{$common_pid}{bytes_written} += $count; 88 $writes{$common_pid}{total_writes}++; 88 $writes{$common_pid}{total_writes}++; 89 $writes{$common_pid}{comm} = $common_comm; 89 $writes{$common_pid}{comm} = $common_comm; 90 } 90 } 91 91 92 sub trace_begin 92 sub trace_begin 93 { 93 { 94 my $sa = POSIX::SigAction->new(\&set_print 94 my $sa = POSIX::SigAction->new(\&set_print_pending); 95 $sa->flags(SA_RESTART); 95 $sa->flags(SA_RESTART); 96 $sa->safe(1); 96 $sa->safe(1); 97 POSIX::sigaction(SIGALRM, $sa) or die "Can 97 POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n"; 98 alarm 1; 98 alarm 1; 99 } 99 } 100 100 101 sub trace_end 101 sub trace_end 102 { 102 { 103 print_unhandled(); 103 print_unhandled(); 104 print_totals(); 104 print_totals(); 105 } 105 } 106 106 107 sub print_check() 107 sub print_check() 108 { 108 { 109 if ($print_pending == 1) { 109 if ($print_pending == 1) { 110 $print_pending = 0; 110 $print_pending = 0; 111 print_totals(); 111 print_totals(); 112 } 112 } 113 } 113 } 114 114 115 sub set_print_pending() 115 sub set_print_pending() 116 { 116 { 117 $print_pending = 1; 117 $print_pending = 1; 118 alarm $interval; 118 alarm $interval; 119 } 119 } 120 120 121 sub print_totals 121 sub print_totals 122 { 122 { 123 my $count; 123 my $count; 124 124 125 $count = 0; 125 $count = 0; 126 126 127 clear_term(); 127 clear_term(); 128 128 129 printf("\nread counts by pid:\n\n"); 129 printf("\nread counts by pid:\n\n"); 130 130 131 printf("%6s %20s %10s %10s %10s\n", "p 131 printf("%6s %20s %10s %10s %10s\n", "pid", "comm", 132 "# reads", "bytes_req", "bytes_read 132 "# reads", "bytes_req", "bytes_read"); 133 printf("%6s %-20s %10s %10s %10s\n", " 133 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", 134 "----------", "----------", "------ 134 "----------", "----------", "----------"); 135 135 136 foreach my $pid (sort { ($reads{$b}{bytes_ 136 foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=> 137 ($reads{$a}{byt 137 ($reads{$a}{bytes_read} || 0) } keys %reads) { 138 my $comm = $reads{$pid}{comm} || ""; 138 my $comm = $reads{$pid}{comm} || ""; 139 my $total_reads = $reads{$pid}{total_r 139 my $total_reads = $reads{$pid}{total_reads} || 0; 140 my $bytes_requested = $reads{$pid}{byt 140 my $bytes_requested = $reads{$pid}{bytes_requested} || 0; 141 my $bytes_read = $reads{$pid}{bytes_re 141 my $bytes_read = $reads{$pid}{bytes_read} || 0; 142 142 143 printf("%6s %-20s %10s %10s %10s\n 143 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, 144 $total_reads, $bytes_requested, 144 $total_reads, $bytes_requested, $bytes_read); 145 145 146 if (++$count == $nlines) { 146 if (++$count == $nlines) { 147 last; 147 last; 148 } 148 } 149 } 149 } 150 150 151 $count = 0; 151 $count = 0; 152 152 153 printf("\nwrite counts by pid:\n\n"); 153 printf("\nwrite counts by pid:\n\n"); 154 154 155 printf("%6s %20s %10s %13s\n", "pid", " 155 printf("%6s %20s %10s %13s\n", "pid", "comm", 156 "# writes", "bytes_written"); 156 "# writes", "bytes_written"); 157 printf("%6s %-20s %10s %13s\n", "------ 157 printf("%6s %-20s %10s %13s\n", "------", "--------------------", 158 "----------", "-------------"); 158 "----------", "-------------"); 159 159 160 foreach my $pid (sort { ($writes{$b}{bytes 160 foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=> 161 ($writes{$a}{bytes_wri 161 ($writes{$a}{bytes_written} || 0)} keys %writes) { 162 my $comm = $writes{$pid}{comm} || ""; 162 my $comm = $writes{$pid}{comm} || ""; 163 my $total_writes = $writes{$pid}{total 163 my $total_writes = $writes{$pid}{total_writes} || 0; 164 my $bytes_written = $writes{$pid}{byte 164 my $bytes_written = $writes{$pid}{bytes_written} || 0; 165 165 166 printf("%6s %-20s %10s %13s\n", $pi 166 printf("%6s %-20s %10s %13s\n", $pid, $comm, 167 $total_writes, $bytes_written); 167 $total_writes, $bytes_written); 168 168 169 if (++$count == $nlines) { 169 if (++$count == $nlines) { 170 last; 170 last; 171 } 171 } 172 } 172 } 173 173 174 %reads = (); 174 %reads = (); 175 %writes = (); 175 %writes = (); 176 } 176 } 177 177 178 my %unhandled; 178 my %unhandled; 179 179 180 sub print_unhandled 180 sub print_unhandled 181 { 181 { 182 if ((scalar keys %unhandled) == 0) { 182 if ((scalar keys %unhandled) == 0) { 183 return; 183 return; 184 } 184 } 185 185 186 print "\nunhandled events:\n\n"; 186 print "\nunhandled events:\n\n"; 187 187 188 printf("%-40s %10s\n", "event", "count"); 188 printf("%-40s %10s\n", "event", "count"); 189 printf("%-40s %10s\n", "----------------- 189 printf("%-40s %10s\n", "----------------------------------------", 190 "-----------"); 190 "-----------"); 191 191 192 foreach my $event_name (keys %unhandled) { 192 foreach my $event_name (keys %unhandled) { 193 printf("%-40s %10d\n", $event_name, $ 193 printf("%-40s %10d\n", $event_name, $unhandled{$event_name}); 194 } 194 } 195 } 195 } 196 196 197 sub trace_unhandled 197 sub trace_unhandled 198 { 198 { 199 my ($event_name, $context, $common_cpu, $c 199 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, 200 $common_pid, $common_comm, $common_cal 200 $common_pid, $common_comm, $common_callchain) = @_; 201 201 202 $unhandled{$event_name}++; 202 $unhandled{$event_name}++; 203 } 203 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.