Whamcloud - gitweb
land v0.9.1 on HEAD, in preparation for a 1.0.x branch
[fs/lustre-release.git] / lustre / tests / leak_finder.pl
1 #!/usr/bin/perl -w
2
3 use IO::Handle;
4
5 STDOUT->autoflush(1);
6 STDERR->autoflush(1);
7
8 my ($line, $memory);
9 my $debug_line = 0;
10
11 my $total = 0;
12 my $max = 0;
13
14 while ($line = <>) {
15     $debug_line++;
16     my ($file, $func, $lno, $name, $size, $addr, $type);
17     if ($line =~ m/^.*(\.).*\((.*):(\d+):(.*)\(\)\) (k|v|slab-)(.*) '(.*)': (\d+) at (.*) \(tot (.*)\).*$/){
18         $file = $2;
19         $lno  = $3;
20         $func = $4;
21         $type = $6;
22         $name = $7;
23         $size = $8;
24         $addr = $9;
25         $tot  = $10;
26
27         # we can't dump the log after portals has exited, so skip "leaks"
28         # from memory freed in the portals module unloading.
29         if ($func eq 'portals_handle_init') {
30             next;
31         }
32         printf("%8s %6d bytes at %s called %s (%s:%s:%d)\n", $type, $size,
33                $addr, $name, $file, $func, $lno);
34     } else {
35         next;
36     }
37
38     if (index($type, 'alloced') >= 0) {
39         if (defined($memory->{$addr})) {
40             print STDERR "*** Two allocs with the same address ($size bytes at $addr, $file:$func:$lno)\n";
41             print STDERR "    first malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, second at $file:$func:$lno\n";
42             next;
43         }
44
45         $memory->{$addr}->{name} = $name;
46         $memory->{$addr}->{size} = $size;
47         $memory->{$addr}->{file} = $file;
48         $memory->{$addr}->{func} = $func;
49         $memory->{$addr}->{lno} = $lno;
50         $memory->{$addr}->{debug_line} = $debug_line;
51
52         $total += $size;
53         if ($total > $max) {
54             $max = $total;
55         }
56     } else {
57         if (!defined($memory->{$addr})) {
58             print STDERR "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
59             next;
60         }
61         my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$addr};
62
63         if ($memory->{$addr}->{size} != $size) {
64             print STDERR "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
65             print STDERR "    malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
66             next;
67         }
68
69         delete $memory->{$addr};
70         $total -= $size;
71     }
72     if ($total != int($tot)) {
73         print "kernel total $tot != my total $total\n";
74         $total = $tot;
75     }
76 }
77
78 # Sort leak output by allocation time
79 my @sorted = sort {
80     return $memory->{$a}->{debug_line} <=> $memory->{$b}->{debug_line};
81 } keys(%{$memory});
82
83 my $key;
84 foreach $key (@sorted) {
85     my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key};
86     print STDERR "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
87 }
88
89 print STDERR "maximum used: $max, amount leaked: $total\n";