#!/usr/bin/perl # llobdstat is a utility that parses obdfilter statistics files # found at proc/fs/lustre//stats. # It is mainly useful to watch the statistics change over time. my $pname = $0; my $defaultpath = "/proc/fs/lustre"; my $obdstats = "stats"; sub usage() { print STDERR "Usage: $pname [ [}]\n"; print STDERR "where ost_name : ost name under $defaultpath/obdfilter\n"; print STDERR " interval : sample interaval in seconds\n"; print STDERR "example: $pname lustre-OST0000 2\n"; print STDERR "Use CTRL + C to stop statistics printing\n"; exit 1; } my $statspath = "None"; my $interval = 0; my $counter = undef; if (($#ARGV < 0) || ($#ARGV > 2)) { usage(); } else { if ( $ARGV[0] =~ /help$/ ) { usage(); } if ( -f $ARGV[0] ) { $statspath = $ARGV[0]; } elsif ( -f "$ARGV[0]/$obdstats" ) { $statspath = "$ARGV[0]/$obdstats"; } else { my $st = "$defaultpath/obdfilter/$ARGV[0]/$obdstats"; if ( -f "$st" ) { $statspath = $st; } } if ( $statspath =~ /^None$/ ) { die "Cannot locate stat file for: $ARGV[0]\n"; } if ($#ARGV > 0) { $interval = $ARGV[1]; } if ($#ARGV > 1) { $counter = $ARGV[2]; } } print "$pname on $statspath\n"; my %cur; my %last; my $mhz = 0; # Removed some statstics like open, close that obdfilter doesn't contain. # To add statistics parameters one needs to specify parameter names in the # below declarations in the same sequence. my ($read_bytes, $write_bytes, $create, $destroy, $statfs, $punch, $snapshot_time) = ("read_bytes", "write_bytes", "create", "destroy", "statfs", "punch", "snapshot_time"); my @extinfo = ($create, $destroy, $statfs, $punch); my %shortname = ($create => "cx", $destroy => "dx", $statfs => "st", $punch => "pu"); sub get_cpumhz() { my $cpu_freq; my $itc_freq; # On Itanium systems use this if (open(CPUINFO, "/proc/cpuinfo")==0) { return; } while () { if (/^cpu MHz\s+:\s*([\d\.]+)/) { $cpu_freq=$1; } elsif (/^itc MHz\s+:\s*([\d\.]+)/) { $itc_freq=$1; } } if (defined($itc_freq)) { $mhz = $itc_freq; } elsif (defined($cpu_freq)) { $mhz = $cpu_freq; } else { $mhz = 1; } close CPUINFO; } get_cpumhz(); print "Processor counters run at $mhz MHz\n"; # read statistics from obdfilter stats file. # This subroutine gets called after every interval specified by user. sub readstat() { my $prevcount; my @iodata; seek STATS, 0, 0; while () { chop; # ($name, $cumulcount, $samples, $unit, $min, $max, $sum, $sumsquare) @iodata = split(/\s+/, $_); my $name = $iodata[0]; $prevcount = $cur{$name}; if (defined($prevcount)) { $last{$name} = $prevcount; } if ($name =~ /^read_bytes$/ || $name =~ /^write_bytes$/) { $cur{$name} = $iodata[6]; } elsif ($name =~ /^snapshot_time$/) { # $cumulcount =~ /(\d+)/; $cur{$name} = $iodata[1]; } else { $cur{$name} = $iodata[1]; } } } # process stats information read from obdfilter stats file. # This subroutine gets called after every interval specified by user. sub process_stats() { my $delta; my $data; my $last_time = $last{$snapshot_time}; if (!defined($last_time)) { printf "Read: %-g, Write: %-g, create/destroy: %-g/%-g, stat: %-g, punch: %-g\n", $cur{$read_bytes}, $cur{$write_bytes}, $cur{$create}, $cur{$destroy}, $cur{$statfs}, $cur{$punch}; if ($interval) { print "[NOTE: cx: create, dx: destroy, st: statfs, pu: punch ]\n\n"; print "Timestamp Read-delta ReadRate Write-delta WriteRate\n"; print "--------------------------------------------------------\n"; } } else { my $timespan = $cur{$snapshot_time} - $last{$snapshot_time}; my $rdelta = $cur{$read_bytes} - $last{$read_bytes}; my $rrate = ($rdelta) / ($timespan * ( 1 << 20 )); my $wdelta = $cur{$write_bytes} - $last{$write_bytes}; my $wrate = ($wdelta) / ($timespan * ( 1 << 20 )); $rdelta = ($rdelta) / (1024 * 1024); $wdelta = ($wdelta) / (1024 * 1024); # This print repeats after every interval. printf "%10lu %6.2fMB %6.2fMB/s %6.2fMB %6.2fMB/s", $cur{$snapshot_time}, $rdelta, $rrate, $wdelta, $wrate; $delta = $cur{$getattr} - $last{$getattr}; if ( $delta != 0 ) { $rdelta = int ($delta/$timespan); print " ga:$delta,$rdelta/s"; } for $data ( @extinfo ) { $delta = $cur{$data} - $last{$data}; if ($delta != 0) { print " $shortname{$data}:$delta"; } } print "\n"; $| = 1; } } #Open the obdfilter stat file with STATS open(STATS, $statspath) || die "Cannot open $statspath: $!\n"; do { # read the statistics from stat file. readstat(); process_stats(); if ($interval) { sleep($interval); %last = %cur; } # Repeat the statistics printing after every "interval" specified in # command line, up to counter times, if specified } while ($interval && (defined($counter) ? $counter-- > 0 : 1)); close STATS; # llobdfilter.pl ends here.