check-all revision 1.1
11.1Sperseant#!/usr/pkg/bin/perl 21.1Sperseant 31.1Sperseant# 41.1Sperseant# Use dumplfs to find all locations of the Ifile inode on a given disk. 51.1Sperseant# Order these by serial number and call fsck_lfs on the raw disk for each. 61.1Sperseant# If any fsck gives errors (lines containing "!", with a few exceptions) 71.1Sperseant# print an error code with the daddr of the failing Ifile inode location. 81.1Sperseant# 91.1Sperseant 101.1Sperseant$rdev = $ARGV[0]; 111.1Sperseant$sstart = $ARGV[1]; 121.1Sperseant$rollid = 0; 131.1Sperseantopen(DUMPLFS, "dumplfs $rdev |"); 141.1Sperseant 151.1Sperseant# Look for "roll_id" so we don't use garbage 161.1Sperseantwhile (<DUMPLFS>) { 171.1Sperseant if (m/roll_id *([x0-9a-f]*)/) { 181.1Sperseant $rollid = $1; 191.1Sperseant last; 201.1Sperseant } 211.1Sperseant} 221.1Sperseant 231.1Sperseant# Now look for inodes and segment summaries. Build a hash table of these 241.1Sperseant# based on serial number. Ignore any with serial numbers lower than $sstart. 251.1Sperseant 261.1Sperseant%iloc = (); 271.1Sperseantwhile (<DUMPLFS>) { 281.1Sperseant if (m/roll_id *([0-9a-f]*)/) { 291.1Sperseant # print "rollid $1\n"; 301.1Sperseant if ("0x$1" ne $rollid) { 311.1Sperseant # Skip the rest of this segment 321.1Sperseant while(<DUMPLFS>) { 331.1Sperseant last if m/SEGMENT/; 341.1Sperseant } 351.1Sperseant next; 361.1Sperseant } 371.1Sperseant } 381.1Sperseant if (m/serial *([0-9]*)/) { 391.1Sperseant $serno = $1; 401.1Sperseant # print "serno $serno\n"; 411.1Sperseant if ($serno < $sstart) { 421.1Sperseant # Skip the rest of this partial segment 431.1Sperseant while(<DUMPLFS>) { 441.1Sperseant last if m/Segment Summary/; 451.1Sperseant } 461.1Sperseant next; 471.1Sperseant } 481.1Sperseant } 491.1Sperseant if (m/0x([0-9a-f]*)/) { 501.1Sperseant foreach $ss (split "0x", $_) { 511.1Sperseant if ($ss =~ m/^([0-9a-f][0-9a-f]*)/) { 521.1Sperseant # print "iblk 0x$1\n"; 531.1Sperseant $daddr = $1; 541.1Sperseant if (m/[^0-9]1v1/) { 551.1Sperseant # print "** ifblk 0x$daddr\n"; 561.1Sperseant $iloc{$serno} = $daddr; 571.1Sperseant } 581.1Sperseant } 591.1Sperseant } 601.1Sperseant } 611.1Sperseant if (m/SEGMENT/) { 621.1Sperseant print; 631.1Sperseant } 641.1Sperseant} 651.1Sperseantclose(DUMPLFS); 661.1Sperseant 671.1Sperseant# 681.1Sperseant# Now fsck each checkpoint in turn, beginning with $sstart. 691.1Sperseant# Look for lines containing only caps or "!", but ignore known 701.1Sperseant# false positives. 711.1Sperseant# 721.1Sperseant$error = 0; 731.1Sperseantopen(LOG, ">>check-all.log"); 741.1Sperseantforeach $k (sort { $a <=> $b } keys %iloc) { 751.1Sperseant $a = $iloc{$k}; 761.1Sperseant print "fsck_lfs -n -f -i 0x$a $ARGV[0]\n"; 771.1Sperseant open(FSCK, "fsck_lfs -n -f -i 0x$a $ARGV[0] |"); 781.1Sperseant while(<FSCK>) { 791.1Sperseant print LOG; 801.1Sperseant chomp; 811.1Sperseant 821.1Sperseant # Known false positives (mismatch between sb and ifile, 831.1Sperseant # which should be expected given we're using an arbitrarily 841.1Sperseant # old version fo the ifile) 851.1Sperseant if (m/AVAIL GIVEN/ || 861.1Sperseant m/BFREE GIVEN/ || 871.1Sperseant m/DMETA GIVEN/ || 881.1Sperseant m/NCLEAN GIVEN/) { 891.1Sperseant next; 901.1Sperseant } 911.1Sperseant 921.1Sperseant # Fsck reports errors in ALL CAPS 931.1Sperseant # But don't count hex numbers as "lowercase". 941.1Sperseant s/0x[0-9a-f]*//g; 951.1Sperseant if (m/[A-Z]/ && ! m/[a-z]/) { 961.1Sperseant $error = 1; 971.1Sperseant last; 981.1Sperseant } 991.1Sperseant } 1001.1Sperseant close(FSCK); 1011.1Sperseant print "$error $k 0x$a\n"; 1021.1Sperseant last if $error; 1031.1Sperseant} 1041.1Sperseant 1051.1Sperseant# If there were no checkpoints, print *something* 1061.1Sperseantif ($#iloc == 0) { 1071.1Sperseant print "0 $sstart 0\n"; 1081.1Sperseant} 109