Update xfsprogs to latest kernel headers and functions
[xfstests-dev.git] / tools / db-walk
1 #!/usr/bin/perl -w
2 #
3 #  Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # use db to try to traverse the entire filesystem starting at the root
6 #
7 #                                                       dxm 5/10/00
8
9 my $device;
10 my $rootino;
11 my $agcount;
12 my $versionnum;
13 my $dir_version;
14 my @dir_inodes;
15 my @bmap_blocks;
16 my @block_inodes;
17 my $mode;
18
19 sub db($)
20 {
21     my ($args)=@_;
22     my ($ret);
23     
24     $ret=`xfs_db -r $args $device 2> /dev/null`;
25     die "ERROR executing xfs_db -r $args $device" if ($?);
26     
27     return $ret;
28 }
29
30 sub fmt($)
31 {
32     my ($text)=@_;
33     my $c=0;
34     print "        ";
35     foreach (split("\n",$text)) {
36         s/^core\.//;
37         
38         if ($c+length($_) >= 70) {
39             $c=0;
40             print ",\n        ";
41         }
42         if ($c) {
43             print ", ";
44             $c+=2;
45         }
46         print "$_";
47         $c+=length($_)+2;
48     }
49     print "\n";
50 }
51
52 sub inode($)
53 {
54     my ($num)=@_;
55     my ($t);
56     
57     @dir_inodes=();
58     
59     $t=db("-c \"inode $num\" -c \"print\"");
60     print "    *** Inode $num\n";
61     fmt($t);
62     
63     ($mode)= $t=~ /^core.mode = (\d+)$/m;
64     
65     if ($t=~ /a\.bmx/m) {
66         bmap("inode $num","attr");
67         foreach (@bmap_blocks) {
68             attr_block($_);
69         }
70     }
71     if (eval "$mode & 040000") {
72         if ( $t=~ /sfdir/m) {
73             while ($t=~ /inumber(?:\.i[48])? = (\d+)$/mg) {
74                 push(@dir_inodes,$1);
75             }
76         }
77         if ( $t=~ /u\.bmx/m) {
78             bmap("inode $num","dir");
79             foreach (@bmap_blocks) {
80                 dir_block($_);
81                 push(@dir_inodes,@block_inodes);
82             }
83         }
84     } else {
85         bmap("inode $num","file") if ( $t=~ /u\.bmx/m);
86     }
87 }
88
89 sub bmap($$)
90 {
91     my ($cmd,$type)=@_;
92     my ($t);
93     
94     @bmap_blocks=();
95     
96     $flag=($type eq "attr")?"-a":"";
97     
98     $t=db("-c \"$cmd\" -c \"bmap $flag\"");
99     print "    *** bmap $type $cmd\n";
100     fmt($t);
101     
102     if ($type eq "dir" || $type eq "attr") {
103         while ($t=~ /startblock (\d+) \(.+\) count (\d+)/mg) {
104             for ($b=$1;$b<$1+$2;$b++) {
105                 push(@bmap_blocks,$b);
106             }
107         }
108     }
109 }
110
111 sub dir_block($)
112 {
113     my ($num)=@_;
114     my ($t);
115     
116     @block_inodes=();
117     
118     $type=($dir_version==2)?"dir2":"dir";
119     
120     $t=db("-c \"fsblock $num\" -c \"type $type\" -c \"print\"");
121     print "    *** $type block $num\n";
122     # need to drop . and ..
123     ($self)= $t=~ /\[(\d+)\].name = \"\.\"/m;
124     ($parent)= $t=~ /\[(\d+)\].name = \"\.\.\"/m;
125     fmt($t);
126     
127     
128     while ($t=~ /\[(\d+)\].inumber = (\d+)/mg) {
129         next if (defined $self && $1 == $self);
130         next if (defined $parent && $1 == $parent);
131         push(@block_inodes, $2);
132     }
133 }
134
135 sub attr_block($)
136 {
137     my ($num)=@_;
138     my ($t);
139     
140     $t=db("-c \"fsblock $num\" -c \"type attr\" -c \"print\"");
141     print "    *** attr block $num\n";
142
143     fmt($t);
144 }
145
146 sub sb($)
147 {
148     my ($num)=@_;
149     my ($t);
150     
151     $t=db("-c \"sb $num\" -c \"print\"");
152     print "    *** SB $num\n";
153     fmt($t);
154     
155     ($rootino)= $t=~ /^rootino = (\d+)$/m;
156     ($agcount)= $t=~ /^agcount = (\d+)$/m;
157     ($versionnum)= $t=~ /^versionnum = (0x[\da-f]+)$/m;
158     $dir_version = (eval "$versionnum & 0x2000")?2:1;
159 }
160
161 die "Usage: $0 <XFS device>\n" unless (@ARGV == 1);
162
163 $device=shift @ARGV;
164 die "can't read $device\n" unless (-r $device);
165 die "$device is not a block device\n" unless (-b _);
166
167 chomp($HOST = `hostname -s`);
168
169 print "*** db-walk host $HOST device $device\n";
170
171 sb(0);
172 for ($ag=1;$ag<$agcount;$ag++) {
173     sb($ag);
174 }
175
176 @inodes=($rootino);
177 while ($_ = shift @inodes) {
178     inode($_);
179     push(@inodes,@dir_inodes);
180 }