3 # Copyright (c) 2001-2008 Silicon Graphics, Inc. All Rights Reserved.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation.
9 # This program is distributed in the hope that it would be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 # srcdiff is used to compare current user level code with the current
20 # kernel code and advise of any differences between files which are
21 # sharing some or all of their content.
23 # There are two classes of sharing which we will check - header files
24 # in the include directory, which must be exactly the same (use diff)
25 # and source files which contain routines which must be exactly the
26 # same (but the userland file is always a subset of the kernel file,
27 # and hence a more flexible mechanism to "diff" is required).
29 # NB: to cross check that srcdiff is finding all the functions in the
30 # user source file, providing you have "mkproto" installed, you
31 # can "cd xfsprogs/libxfs" and cut&paste this in a bourne shell:
32 # $ for file in xfs_*.c; do
33 # > mkproto -nps < $file | perl -ne '
34 # > END { print " $count\t- " }
35 # > s/^.* (xfs\w+|\*xfs\w+|xlog\w+|\*xlog\w+) \(.*/\1/ && { $count++ }'
38 # (compare this to "srcdiff | fgrep Total:")
43 die "WORKAREA not set" unless defined $ENV{'WORKAREA'};
44 die "KWORKAREA not set" unless defined $ENV{'KWORKAREA'};
45 die "DMWORKAREA not set" unless defined $ENV{'DMWORKAREA'};
46 chdir $ENV{'WORKAREA'};
47 my $dmworkarea = $ENV{'DMWORKAREA'};
48 my $kworkarea = $ENV{'KWORKAREA'};
49 my $xdiff = $ENV{'XDIFF'};
53 if ( ! -f "$kworkarea/xfs_fs.h" ) {
54 $kworkarea .= '/fs/xfs';
55 die "Cannot find XFS in KWORKAREA" unless -f "$kworkarea/xfs_fs.h";
57 die "Cannot find DMAPI in DMWORKAREA" unless -f "$dmworkarea/dmapi.h";
63 print STDERR "Illegal option $_\n";
69 print STDERR "Usage: $0 [-q]\n";
73 my @pkglist = qw( xfstests attr acl dmapi xfsdump xfsprogs );
75 xfs_ag.h xfs_alloc.h xfs_alloc_btree.h xfs_arch.h
76 xfs_attr_leaf.h xfs_attr_sf.h xfs_bit.h xfs_bmap.h
77 xfs_bmap_btree.h xfs_btree.h xfs_buf_item.h
78 xfs_da_btree.h xfs_dfrag.h xfs_dinode.h
79 xfs_dir2.h xfs_dir2_block.h xfs_dir2_data.h
80 xfs_dir2_leaf.h xfs_dir2_node.h xfs_dir2_sf.h
81 xfs_extfree_item.h xfs_ialloc.h
82 xfs_imap.h xfs_ialloc_btree.h xfs_inode.h xfs_inode_item.h
83 xfs_inum.h xfs_log.h xfs_log_priv.h xfs_log_recover.h
84 xfs_mount.h xfs_quota.h xfs_rtalloc.h
85 xfs_sb.h xfs_trans.h xfs_trans_space.h xfs_types.h xfs_fs.h
89 my ( $file, $prefix1, $prefix2 ) = @_;
91 `diff $prefix1/$file $prefix2/$file >/dev/null 2>&1`;
93 print sprintf("\t%-35s ... ", $file);
94 if ($? != 0) { printf("FAILED\n(%s/%s differs to %s/%s)\n",
95 $prefix1, $file, $prefix2, $file); }
96 else { print "ok\n"; }
98 printf("\t%-35s ... FAILED\n(%s/%s differs to %s/%s)\n",
99 $file, $prefix1, $file, $prefix2, $file);
100 if (defined($xdiff)) {
101 `$xdiff $prefix1/$file $prefix2/$file`;
107 # xfstests directory m4 directory is a repository of all of the
108 # custom m4 macros used in the packages we look after.
111 my ( $package ) = @_;
113 foreach (`ls $package/m4/*.m4`) {
114 my $m4 = `basename $_`;
116 straightdiff $m4, "$package/m4", "xfstests/m4";
120 my $first = shift @pkglist;
122 print "\n=== Checking $_ package ===\n";
124 straightdiff 'buildrules', "$first/include", "$_/include";
125 straightdiff 'buildmacros', "$first/include", "$_/include";
126 straightdiff 'Makefile', "$first/build", "$_/build";
127 straightdiff 'Makefile', "$first/build/rpm", "$_/build/rpm";
128 straightdiff 'Makefile', "$first/build/tar", "$_/build/tar";
130 print "\n=== Checking headers ===\n";
131 foreach (@difflist) {
132 straightdiff $_, 'xfsprogs/include', "$kworkarea";
134 straightdiff 'dmapi_kern.h', 'dmapi/include', "$dmworkarea";
135 straightdiff 'dmapi.h', 'dmapi/include', "$dmworkarea";
139 # Implements a tri-state FSA, see comments for state transitions
140 # (knows about the way the XFS kernel code is written, & makes
141 # some assumptions so as to not need to parse generic C code).
142 # Accepts one line at a time from a source file, picking out the
143 # function bodies so they can be subsequently compared.
146 my $line; # line number in current source file
147 my $state; # current FSA state
148 my $funcbody; # current function body (contents)
151 my ( $newline ) = @_;
155 # if line looks like start of a function, transition to 1
156 # & squirrel line away as line 1 of current function
158 if ($newline =~ m/^[xfs|xlog]/) {
160 $funcbody = $newline;
165 # if line looks like start of a function, stay here
166 # & squirrel line away as line 1 of current function
167 # otherwise if line isn't start of function body,
168 # squirrel line away as next line of current function
169 # (args/..., but not sure this is a real function yet)
170 # otherwise (start of function)
171 # squirrel line away as next line of current function
172 # transition to state 2
173 elsif ($state == 1) {
174 if ($newline =~ m/^[xfs|xlog]/) {
175 $funcbody = $newline;
177 elsif ($newline =~ m/^\{/) {
179 $funcbody .= $newline;
184 # if line looks like end of function body,
185 # squirrel line away as last line of current function
186 # tell someone we have a complete function ready
187 # transition to state 0
189 # squirrel line away as next line of current function
190 elsif ($state == 2) {
191 $funcbody .= $newline;
192 if ($newline =~ m/^\}/) {
199 die "unknown state transition";
201 return undef; # i.e. not at end of a function
211 open(USER, "$file") || die "cannot open $file";
213 my $func = setstate($_);
214 push @funcs, $func if (defined($func)); # store function away
227 open(KERN, "$file") || die "cannot open $file";
229 my $func = setstate($_);
230 if (defined($func)) {
231 $func =~ m/^([xfs|xlog]\w+)\s*\(/;
232 next unless defined($1);
234 if (defined($func)) {
235 $funcs{$name} = $func; # store function away
244 my ( $sa, $sb ) = @_;
246 return unless defined($xdiff);
248 open(FILEA, "> /tmp/diff.user.$$") || die "cannot write to /tmp/diff.user.$$";
249 open(FILEB, "> /tmp/diff.kern.$$") || die "cannot write to /tmp/diff.kern.$$";
254 `$xdiff /tmp/diff.user.$$ /tmp/diff.kern.$$`;
255 unlink ("/tmp/diff.user.$$","/tmp/diff.kern.$$");
259 my ( $file, $prefix1, $prefix2 ) = @_;
265 print "\n=== Checking $file routines ===\n" unless ($quiet);
267 # iterate over user funcs, match up to kernel funcs
269 my @user = listfuncs "$prefix1/$file";
270 my %kern = hashfuncs "$prefix2/$file";
272 foreach my $userfunc (@user) {
274 $userfunc =~ m/^([xfs|xlog]\w+)\s*\(/;
275 next unless (defined($1));
279 if (exists($kern{$name})) {
280 if ($userfunc ne $kern{$name}) {
281 print "\n=== $file routines ===\n"
282 if (!$found++ && $quiet);
284 printf("\t%-35s ... ", $name);
286 diffme $userfunc, $kern{$name};
289 printf("\t%-35s ... ", $name);
294 print "Cannot find kernel function $userfunc";
295 print " in file $prefix2/$file\n";
298 ($count != 1) && ( $plural = 's' );
299 print "( Total: $count routine$plural checked in $file )\n" unless ($quiet);
302 # xfsprogs/{libxfs,libxlog}/* fs/xfs/*
304 xfs_alloc.c xfs_alloc_btree.c xfs_attr.c xfs_attr_leaf.c
305 xfs_bmap.c xfs_bmap_btree.c xfs_btree.c xfs_da_btree.c
306 xfs_dir2.c xfs_dir2_block.c xfs_dir2_data.c xfs_dir2_leaf.c
307 xfs_dir2_node.c xfs_dir2_sf.c xfs_ialloc.c xfs_ialloc_btree.c
308 xfs_inode.c xfs_mount.c xfs_rtalloc.c xfs_trans.c
311 print "\n=== Checking libxfs code ===\n";
312 foreach (@funclist) {
313 functiondiff $_, 'xfsprogs/libxfs', "$kworkarea";
315 print "\n=== Checking libxlog code ===\n";
316 functiondiff 'xfs_log_recover.c', 'xfsprogs/libxlog', "$kworkarea";