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