162306a36Sopenharmony_ci#!/usr/bin/perl -w
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
362306a36Sopenharmony_ci# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci# read/write top
662306a36Sopenharmony_ci#
762306a36Sopenharmony_ci# Periodically displays system-wide r/w call activity, broken down by
862306a36Sopenharmony_ci# pid.  If an [interval] arg is specified, the display will be
962306a36Sopenharmony_ci# refreshed every [interval] seconds.  The default interval is 3
1062306a36Sopenharmony_ci# seconds.
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciuse 5.010000;
1362306a36Sopenharmony_ciuse strict;
1462306a36Sopenharmony_ciuse warnings;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciuse lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
1762306a36Sopenharmony_ciuse lib "./Perf-Trace-Util/lib";
1862306a36Sopenharmony_ciuse Perf::Trace::Core;
1962306a36Sopenharmony_ciuse Perf::Trace::Util;
2062306a36Sopenharmony_ciuse POSIX qw/SIGALRM SA_RESTART/;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cimy $default_interval = 3;
2362306a36Sopenharmony_cimy $nlines = 20;
2462306a36Sopenharmony_cimy $print_thread;
2562306a36Sopenharmony_cimy $print_pending = 0;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cimy %reads;
2862306a36Sopenharmony_cimy %writes;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cimy $interval = shift;
3162306a36Sopenharmony_ciif (!$interval) {
3262306a36Sopenharmony_ci    $interval = $default_interval;
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cisub syscalls::sys_exit_read
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
3862306a36Sopenharmony_ci	$common_pid, $common_comm, $common_callchain,
3962306a36Sopenharmony_ci	$nr, $ret) = @_;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci    print_check();
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci    if ($ret > 0) {
4462306a36Sopenharmony_ci	$reads{$common_pid}{bytes_read} += $ret;
4562306a36Sopenharmony_ci    } else {
4662306a36Sopenharmony_ci	if (!defined ($reads{$common_pid}{bytes_read})) {
4762306a36Sopenharmony_ci	    $reads{$common_pid}{bytes_read} = 0;
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci	$reads{$common_pid}{errors}{$ret}++;
5062306a36Sopenharmony_ci    }
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cisub syscalls::sys_enter_read
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
5662306a36Sopenharmony_ci	$common_pid, $common_comm, $common_callchain,
5762306a36Sopenharmony_ci	$nr, $fd, $buf, $count) = @_;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci    print_check();
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci    $reads{$common_pid}{bytes_requested} += $count;
6262306a36Sopenharmony_ci    $reads{$common_pid}{total_reads}++;
6362306a36Sopenharmony_ci    $reads{$common_pid}{comm} = $common_comm;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cisub syscalls::sys_exit_write
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
6962306a36Sopenharmony_ci	$common_pid, $common_comm, $common_callchain,
7062306a36Sopenharmony_ci	$nr, $ret) = @_;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci    print_check();
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci    if ($ret <= 0) {
7562306a36Sopenharmony_ci	$writes{$common_pid}{errors}{$ret}++;
7662306a36Sopenharmony_ci    }
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cisub syscalls::sys_enter_write
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
8262306a36Sopenharmony_ci	$common_pid, $common_comm, $common_callchain,
8362306a36Sopenharmony_ci	$nr, $fd, $buf, $count) = @_;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci    print_check();
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci    $writes{$common_pid}{bytes_written} += $count;
8862306a36Sopenharmony_ci    $writes{$common_pid}{total_writes}++;
8962306a36Sopenharmony_ci    $writes{$common_pid}{comm} = $common_comm;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cisub trace_begin
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci    my $sa = POSIX::SigAction->new(\&set_print_pending);
9562306a36Sopenharmony_ci    $sa->flags(SA_RESTART);
9662306a36Sopenharmony_ci    $sa->safe(1);
9762306a36Sopenharmony_ci    POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n";
9862306a36Sopenharmony_ci    alarm 1;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cisub trace_end
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci    print_unhandled();
10462306a36Sopenharmony_ci    print_totals();
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cisub print_check()
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci    if ($print_pending == 1) {
11062306a36Sopenharmony_ci	$print_pending = 0;
11162306a36Sopenharmony_ci	print_totals();
11262306a36Sopenharmony_ci    }
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cisub set_print_pending()
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci    $print_pending = 1;
11862306a36Sopenharmony_ci    alarm $interval;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cisub print_totals
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci    my $count;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci    $count = 0;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci    clear_term();
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci    printf("\nread counts by pid:\n\n");
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci    printf("%6s  %20s  %10s  %10s  %10s\n", "pid", "comm",
13262306a36Sopenharmony_ci	   "# reads", "bytes_req", "bytes_read");
13362306a36Sopenharmony_ci    printf("%6s  %-20s  %10s  %10s  %10s\n", "------", "--------------------",
13462306a36Sopenharmony_ci	   "----------", "----------", "----------");
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci    foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=>
13762306a36Sopenharmony_ci			       ($reads{$a}{bytes_read} || 0) } keys %reads) {
13862306a36Sopenharmony_ci	my $comm = $reads{$pid}{comm} || "";
13962306a36Sopenharmony_ci	my $total_reads = $reads{$pid}{total_reads} || 0;
14062306a36Sopenharmony_ci	my $bytes_requested = $reads{$pid}{bytes_requested} || 0;
14162306a36Sopenharmony_ci	my $bytes_read = $reads{$pid}{bytes_read} || 0;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	printf("%6s  %-20s  %10s  %10s  %10s\n", $pid, $comm,
14462306a36Sopenharmony_ci	       $total_reads, $bytes_requested, $bytes_read);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (++$count == $nlines) {
14762306a36Sopenharmony_ci	    last;
14862306a36Sopenharmony_ci	}
14962306a36Sopenharmony_ci    }
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci    $count = 0;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci    printf("\nwrite counts by pid:\n\n");
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci    printf("%6s  %20s  %10s  %13s\n", "pid", "comm",
15662306a36Sopenharmony_ci	   "# writes", "bytes_written");
15762306a36Sopenharmony_ci    printf("%6s  %-20s  %10s  %13s\n", "------", "--------------------",
15862306a36Sopenharmony_ci	   "----------", "-------------");
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci    foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=>
16162306a36Sopenharmony_ci			($writes{$a}{bytes_written} || 0)} keys %writes) {
16262306a36Sopenharmony_ci	my $comm = $writes{$pid}{comm} || "";
16362306a36Sopenharmony_ci	my $total_writes = $writes{$pid}{total_writes} || 0;
16462306a36Sopenharmony_ci	my $bytes_written = $writes{$pid}{bytes_written} || 0;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	printf("%6s  %-20s  %10s  %13s\n", $pid, $comm,
16762306a36Sopenharmony_ci	       $total_writes, $bytes_written);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (++$count == $nlines) {
17062306a36Sopenharmony_ci	    last;
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci    }
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci    %reads = ();
17562306a36Sopenharmony_ci    %writes = ();
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cimy %unhandled;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cisub print_unhandled
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci    if ((scalar keys %unhandled) == 0) {
18362306a36Sopenharmony_ci	return;
18462306a36Sopenharmony_ci    }
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci    print "\nunhandled events:\n\n";
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci    printf("%-40s  %10s\n", "event", "count");
18962306a36Sopenharmony_ci    printf("%-40s  %10s\n", "----------------------------------------",
19062306a36Sopenharmony_ci	   "-----------");
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci    foreach my $event_name (keys %unhandled) {
19362306a36Sopenharmony_ci	printf("%-40s  %10d\n", $event_name, $unhandled{$event_name});
19462306a36Sopenharmony_ci    }
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cisub trace_unhandled
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci    my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
20062306a36Sopenharmony_ci	$common_pid, $common_comm, $common_callchain) = @_;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci    $unhandled{$event_name}++;
20362306a36Sopenharmony_ci}
204