Viewing: llanalyze
#!/usr/bin/perl
use Getopt::Long;
use Term::ANSIColor;
GetOptions("pid=i" => \$pid,
"trace!" => \$trace,
"silent!" => \$silent,
"rpctrace!" => \$rpctrace,
"nodlm!" => \$nodlm,
"dlm_ns=s" => \$dlm_ns,
"noclass!" => \$noclass,
"nonet!" => \$nonet,
"extract_start=s" => \$extract_start,
"extract_end=s" => \$extract_end);
$subsys->{UNDEFINED} = 1 << 0;
$subsys->{MDC} = 1 << 1;
$subsys->{MDS} = 1 << 2;
$subsys->{OSC} = 1 << 3;
$subsys->{OST} = 1 << 4;
$subsys->{CLASS} = 1 << 5;
$subsys->{LOG} = 1 << 6;
$subsys->{LLITE} = 1 << 7;
$subsys->{RPC} = 1 << 8;
$subsys->{MGMT} = 1 << 9;
$subsys->{LNET} = 1 << 10;
$subsys->{LND} = 1 << 11;
$subsys->{PINGER} = 1 << 12;
$subsys->{FILTER} = 1 << 13;
# /* 1<< 14 unused */
$subsys->{ECHO} = 1 << 15;
$subsys->{LDLM} = 1 << 16;
$subsys->{LOV} = 1 << 17;
$subsys->{LQUOTA} = 1 << 18;
$subsys->{OSD} = 1 << 19;
$subsys->{LFSCK} = 1 << 20;
# /* 1<< 21 unused */
# /* 1<< 22 unused */
$subsys->{LMV} = 1 << 23; #/* b_new_cmd */
# /* 1<< 24 unused */
$subsys->{SEC} = 1 << 25; #/* upcall cache */
$subsys->{GSS} = 1 << 26; #/* b_new_cmd */
# /* 1<< 27 unused */
$subsys->{MGC} = 1 << 28;
$usbsys->{MGS} = 1 << 29;
$subsys->{FID} = 1 << 30; #/* b_new_cmd */
$subsys->{FLD} = 1 << 31; #/* b_new_cmd */
$masks->{TRACE} = 1 << 0; # /* ENTRY/EXIT markers */
$masks->{INODE} = 1 << 1; #
$masks->{SUPER} = 1 << 2; #
$masks->{TTY} = 1 << 3; # /* notification printed to TTY */
$masks->{MALLOC} = 1 << 4; # /* print malloc, free information */
$masks->{CACHE} = 1 << 5; # /* cache-related items */
$masks->{INFO} = 1 << 6; # /* general information */
$masks->{IOCTL} = 1 << 7; # /* ioctl related information */
$masks->{NETERROR} = 1 << 8; # /* network errors */
$masks->{NET} = 1 << 9; # /* network communications */
$masks->{WARNING} = 1 << 10; #
$masks->{BUFFS} = 1 << 11; #
$masks->{OTHER} = 1 << 12; #
$masks->{DENTRY} = 1 << 13; #
$masks->{NETTRACE} = 1 << 14; # /* ENTRY/EXIT markers */
$masks->{PAGE} = 1 << 15; # /* bulk page handling */
$masks->{DLMTRACE} = 1 << 16; #
$masks->{ERROR} = 1 << 17; # /* CERROR} = ...) == CDEBUG} = D_ERROR, ...) */
$masks->{EMERG} = 1 << 18; # /* CEMERG} = ...) == CDEBUG} = D_EMERG, ...) */
$masks->{HA} = 1 << 19; # /* recovery and failover */
$masks->{RPCTRACE} = 1 << 20; # /* recovery and failover */
$masks->{VFSTRACE} = 1 << 21;
$masks->{READA} = 1 << 22; #/* read-ahead */
$masks->{MMAP} = 1 << 23;
$masks->{CONFIG} = 1 << 24;
$masks->{CONSOLE} = 1 << 25;
$masks->{QUOTA} = 1 << 26;
$masks->{SEC} = 1 << 27;
$masks->{LFSCK} = 1 << 28;
$masks->{HSM} = 1 << 29;
sub extractpid
{
$line = shift;
# print "$_\n";
if ($line =~ /(\d+)\:(\d+)\:(\d+\.\d+)\:(\d+\.\d+)\:(\d+)\:(\d+)\:.*/) {
return $6;
}
}
sub extracthostpid
{
$line = shift;
# print "$_\n";
if ($line =~ /(\d+)\:(\d+)\:(\d+\.\d+)\:(\d+)\:(\d+)\:(\d+)\:(\d+)\:.*/) {
return $7;
}
}
sub entering_rpc
{
$_ = shift;
$entering_rpc = /Handling RPC/;
if($entering_rpc) {
$oldpid=$pid;
$pid = extractpid($_);
$leaving_rpc = 0;
}
}
sub leaving_rpc
{
$_ = shift;
$leaving_rpc = /Handled RPC/;
if($leaving_rpc) {
$pid = $oldpid;
$entering_rpc = 0;
}
}
sub entering
{
$_ = shift;
$entering = /Process entered/;
}
sub leaving
{
$_ = shift;
$entering = /Process leaving/;
}
sub getsubsys
{
my ($subsys, $mask) = split ":";
return hex($subsys);
}
sub getmask
{
my ($subsys, $mask) = split ":";
return hex($mask);
}
sub setcolor
{
my $linemask = shift;
my $line = shift;
if ($linemask == $masks->{TRACE}) {
if(leaving($line)){
print color("yellow on_black");
} else {
print color("green on_black");
}
}
if ($linemask == $masks->{DLMTRACE}) {
print color("magenta on_black");
}
if ($linemask == $masks->{DLM}) {
print color("magenta on_black");
}
if ($linemask == $masks->{DENTRY}) {
print color("red on_black");
}
}
sub study_lock
{
$_ = shift;
my $rc;
$rc = /client-side enqueue returned a blocked.* ns: (.*) lock: (.*) lrc: (.*) mode/;
if ($rc) {
$completion_callbacks{$1}->{$2} = $3;
# print color("white");
# print "---CP CB START: $1 $2 $3\n";
# print color("reset");
}
$rc = /client-side enqueue:.* ns: (.*) lock: (.*) lrc: (.*) mode/;
if ($rc) {
# print color("white");
# print "---CP CB END: $1 $2 $3 deleting $completion_callbacks{$1}->{$2}\n";
# print color("reset");
delete $completion_callbacks{$1}->{$2};
}
$rc = /client blocking AST callback handler ns: (.*) lock: (.*) lrc: (.*) mode/;
if ($rc) {
$blocking_callbacks{$1}->{$2} = $3;
# print color("white");
# print "---BL CB START: $1 $2\n";
# print color("reset");
}
$rc = /client blocking callback handler END ns: (.*) lock: (.*) lrc: (.*) mode/;
if ($rc) {
# print color("white");
# print "---BL CB END: $1 $2 $3 deleting $blocking_callbacks{$1}->{$2}\n";
# print color("reset");
delete $blocking_callbacks{$1}->{$2};
}
$rc = /ldlm_lock_addref.*ns: (.*) lock: (.*) lrc: (.*) mode/;
# print color("white");
# print "------>addref ns: $1 lock: $2 lrc: $3\n" if ($rc);
# print color("reset");
$locks{$1}->{$2} = {$3} if ($rc);
$rc = /ldlm_lock_decref.*ns: (.*) lock: (.*) lrc: (.*) mode/;
# print color("white");
# print "------>decref ns: $1 lock: $2 lrc: $3\n" if ($rc);
# print color("reset");
$locks{$1}->{$2} = {$3} if ($rc);
}
sub hanging_locks
{
my $found;
my $ns;
foreach (keys %completion_callbacks) {
$ns = $_;
$found = 0;
foreach (keys %{$completion_callbacks{$ns}}) {
if (!$found) {
print "Unfinished completions in ns $ns: \n";
$found =1;
}
print " lock: $_ lrc: $completion_callbacks{$ns}->{$_}\n";
}
}
foreach (keys %blocking_callbacks) {
$ns = $_;
$found = 0;
foreach (keys %{$blocking_callbacks{$ns}}) {
if (!$found) {
print "Unfinished blocking in ns $ns: \n";
$found =1;
}
printf(" lock: $_ lrc: %s\n", $blocking_callbacks{$ns}->{$_});
}
}
}
sub study_intent
{
$_ = shift;
my $rc;
$rc = /D_IT UP dentry (.*) fsdata/;
delete $it{$1} if ($rc);
$rc = /D_IT DOWN dentry (.*) fsdata/;
$it{$1} = "yes" if ($rc);
}
sub unmatched_intents {
my $found;
foreach (keys %it) {
if (!$found) {
print "Unmatched intents: \n";
$found =1;
}
print " $_\n";
}
}
sub usage
{
print "Usage : llanalyze LOGFILE\n";
exit;
}
if ($ARGV[0]) {
if(!open(LOG, "<$ARGV[0]")){
print "Cannot open $ARGV[0]\n";
exit;
}
} else {
usage();
}
$width = 0;
if ($ARGV[1]) {
$width = $ARGV[1];
}
print "nodlm $nodlm, nonet $nonet, trace $trace\n";
print "pid: $pid, dlm_ns: $dlm_ns\n";
print "rpctrace: $rpctrace\n";
print "extract_start: $extract_start\n";
print "extract_end: $extract_end\n";
print "width: $width\n";
while (<LOG>) {
if ($extract_start && $extract_start ne "LLANAYZE_FOUND") {
next if (index($_, $extract_start, 0) == -1);
$extract_start = "LLANAYZE_FOUND";
}
if ($extract_end) {
next if ($extract_end eq "LLANAYZE_FOUND");
if (index($_, $extract_end, 0) != -1) {
$extract_end = "LLANAYZE_FOUND";
}
}
$linepid = extractpid($_);
$linehpid = extracthostpid($_);
$linemask = getmask($_);
$linesubsys = getsubsys($_);
# printf "---> mask %x subsys %x\n", $linemask, $linesubsys;
if (leaving($_)) {
chop $prefix->{$linepid};
chop $prefix->{$linepid};
}
if ($linemask == $masks->{DENTRY}) {
study_intent($_);
}
if ($linemask == $masks->{DLMTRACE}) {
study_lock($_);
}
if ( !$pid || $linepid == $pid || $linehpid == $pid) {
next if ($rpctrace && !$entering_rpc && $linemask != $masks->{RPCTRACE});
next if ($trace && $linemask != $masks->{TRACE});
next if ($nodlm &&
( $linesubsys == $subsys->{LDLM}));
next if ($dlm_ns &&
( $linesubsys != $subsys->{LDLM}));
next if (($found_dlm_ns = index( $_, $dlm_ns, 0)) == -1);
next if ($noclass &&
( $linesubsys == $subsys->{CLASS}));
next if ($nonet &&
( $linesubsys == $subsys->{RPC} ||
$linesubsys == $subsys->{NET} ||
$linesubsys == $subsys->{LNET} ||
$linesubsys == $subsys->{LND}));
if($rpctrace && !$entering_rpc) {entering_rpc($_);}
if($rpctrace && !$leaving_rpc) {leaving_rpc($_);}
# printf "sub/mask: %s - %s\n", getsubsys($_), getmask($_);
if (!$silent) {
setcolor($linemask, $_);
my $string = $prefix->{$linepid}.$_;
if($width){
$string = substr($string, 0, $width)."\n";
}
printf("%s", $string);
print color("reset");
}
# last if $count++ > 100;
}
if (entering($_)) {
$prefix->{$linepid} .= ' ';
}
}
unmatched_intents();
hanging_locks();
# printf "argv %s pid %d\n", $ARGV[0], extractpid($ARGV[0]);