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