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