check-all revision 1.1
1#!/usr/pkg/bin/perl
2
3#
4# Use dumplfs to find all locations of the Ifile inode on a given disk.
5# Order these by serial number and call fsck_lfs on the raw disk for each.
6# If any fsck gives errors (lines containing "!", with a few exceptions)
7# print an error code with the daddr of the failing Ifile inode location.
8#
9
10$rdev = $ARGV[0];
11$sstart = $ARGV[1];
12$rollid = 0;
13open(DUMPLFS, "dumplfs $rdev |");
14
15# Look for "roll_id" so we don't use garbage
16while (<DUMPLFS>) {
17	if (m/roll_id *([x0-9a-f]*)/) {
18		$rollid = $1;
19		last;
20	}
21}
22
23# Now look for inodes and segment summaries.  Build a hash table of these
24# based on serial number.  Ignore any with serial numbers lower than $sstart.
25
26%iloc = ();
27while (<DUMPLFS>) {
28	if (m/roll_id *([0-9a-f]*)/) {
29		# print "rollid $1\n";
30		if ("0x$1" ne $rollid) {
31			# Skip the rest of this segment
32			while(<DUMPLFS>) {
33				last if m/SEGMENT/;
34			}
35			next;
36		}
37	}
38	if (m/serial *([0-9]*)/) {
39		$serno = $1;
40		# print "serno $serno\n";
41		if ($serno < $sstart) {
42			# Skip the rest of this partial segment
43			while(<DUMPLFS>) {
44				last if m/Segment Summary/;
45			}
46			next;
47		}
48	}
49	if (m/0x([0-9a-f]*)/) {
50		foreach $ss (split "0x", $_) {
51			if ($ss =~ m/^([0-9a-f][0-9a-f]*)/) {
52				# print "iblk 0x$1\n";
53				$daddr = $1;
54				if (m/[^0-9]1v1/) {
55					# print "** ifblk 0x$daddr\n";
56					$iloc{$serno} = $daddr;
57				}
58			}
59		}
60	}
61	if (m/SEGMENT/) {
62		print;
63	}
64}
65close(DUMPLFS);
66
67#
68# Now fsck each checkpoint in turn, beginning with $sstart.
69# Look for lines containing only caps or "!", but ignore known
70# false positives.
71#
72$error = 0;
73open(LOG, ">>check-all.log");
74foreach $k (sort { $a <=> $b } keys %iloc) {
75	$a = $iloc{$k};
76	print "fsck_lfs -n -f -i 0x$a $ARGV[0]\n";
77	open(FSCK, "fsck_lfs -n -f -i 0x$a $ARGV[0] |");
78	while(<FSCK>) {
79		print LOG;
80		chomp;
81
82		# Known false positives (mismatch between sb and ifile,
83		# which should be expected given we're using an arbitrarily
84		# old version fo the ifile)
85		if (m/AVAIL GIVEN/ ||
86		    m/BFREE GIVEN/ ||
87		    m/DMETA GIVEN/ ||
88		    m/NCLEAN GIVEN/) {
89			next;
90		}
91
92		# Fsck reports errors in ALL CAPS
93		# But don't count hex numbers as "lowercase".
94		s/0x[0-9a-f]*//g;
95		if (m/[A-Z]/ && ! m/[a-z]/) {
96			$error = 1;
97			last;
98		}
99	}
100	close(FSCK);
101	print "$error $k 0x$a\n";
102	last if $error;
103}
104
105# If there were no checkpoints, print *something*
106if ($#iloc == 0) {
107	print "0 $sstart 0\n";
108}
109