]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/mtxstat/mtxstat.pl
zfs: merge openzfs/zfs@e0bd8118d
[FreeBSD/FreeBSD.git] / tools / tools / mtxstat / mtxstat.pl
1 #!/usr/bin/perl -Tw
2 #-
3 # Copyright (c) 2002 Dag-Erling Smørgrav
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer
11 #    in this position and unchanged.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 #    notice, this list of conditions and the following disclaimer in the
14 #    documentation and/or other materials provided with the distribution.
15 # 3. The name of the author may not be used to endorse or promote products
16 #    derived from this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #
29 #
30
31 use strict;
32 use Getopt::Std;
33
34 sub usage() {
35
36     print(STDERR "usage: mtxstat [-gr] [-a|c|m|t] [-l limit]\n");
37     exit(1);
38 }
39
40 MAIN:{
41     my %opts;                   # Command-line options
42     my $key;                    # Sort key
43     my $limit;                  # Output limit
44     local *PIPE;                # Pipe
45     my $header;                 # Header line
46     my @names;                  # Field names
47     my %data;                   # Mutex data
48     my @list;                   # List of entries
49
50     getopts("acgl:mrt", \%opts)
51         or usage();
52     if ($opts{'a'}) {
53         usage()
54             if ($opts{'c'} || $opts{'m'} || $opts{'t'});
55         $key = 'avg';
56     } elsif ($opts{'c'}) {
57         usage()
58             if ($opts{'m'} || $opts{'t'});
59         $key = 'count';
60     } elsif ($opts{'m'}) {
61         usage()
62             if ($opts{'t'});
63         $key = 'max';
64     } elsif ($opts{'t'}) {
65         $key = 'total';
66     }
67     if ($opts{'l'}) {
68         if ($opts{'l'} !~ m/^\d+$/) {
69             usage();
70         }
71         $limit = $opts{'l'};
72     }
73     $ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin';
74     open(PIPE, "sysctl -n debug.mutex.prof.stats|")
75         or die("open(): $!\n");
76     $header = <PIPE>;
77     chomp($header);
78     @names = split(' ', $header);
79     if (defined($key) && !grep(/^$key$/, @names)) {
80         die("can't find sort key '$key' in header\n");
81     }
82     while (<PIPE>) {
83         chomp();
84         my @fields = split(' ', $_, @names);
85         next unless @fields;
86         my %entry;
87         foreach (@names) {
88             $entry{$_} = ($_ eq 'name') ? shift(@fields) : 0.0 + shift(@fields);
89         }
90         if ($opts{'g'}) {
91             $entry{'name'} =~ s/^(\S+)\s+\((.*)\)$/$2/;
92         }
93         my $name = $entry{'name'};
94         if ($data{$name}) {
95             if ($entry{'max'} > $data{$name}->{'max'}) {
96                 $data{$name}->{'max'} = $entry{'max'};
97             }
98             $data{$name}->{'total'} += $entry{'total'};
99             $data{$name}->{'count'} += $entry{'count'};
100             $data{$name}->{'avg'} =
101                 $data{$name}->{'total'} / $data{$name}->{'count'};
102         } else {
103             $data{$name} = \%entry;
104         }
105     }
106     if (defined($key)) {
107         @list = sort({ $data{$a}->{$key} <=> $data{$b}->{$key} }
108                      sort(keys(%data)));
109     } else {
110         @list = sort(keys(%data));
111     }
112     if ($opts{'r'}) {
113         @list = reverse(@list);
114     }
115     print("$header\n");
116     if ($limit) {
117         while (@list > $limit) {
118             pop(@list);
119         }
120     }
121     foreach (@list) {
122         printf("%6.0f %12.0f %11.0f %5.0f %-40.40s\n",
123                $data{$_}->{'max'},
124                $data{$_}->{'total'},
125                $data{$_}->{'count'},
126                $data{$_}->{'avg'},
127                $data{$_}->{'name'});
128     }
129 }