head	1.5;
access;
symbols
	netbsd-11-0-RC4:1.5
	netbsd-11-0-RC3:1.5
	netbsd-11-0-RC2:1.5
	netbsd-11-0-RC1:1.5
	perseant-exfatfs-base-20250801:1.5
	netbsd-11:1.5.0.76
	netbsd-11-base:1.5
	netbsd-10-1-RELEASE:1.5
	perseant-exfatfs-base-20240630:1.5
	perseant-exfatfs:1.5.0.74
	perseant-exfatfs-base:1.5
	netbsd-8-3-RELEASE:1.5
	netbsd-9-4-RELEASE:1.5
	netbsd-10-0-RELEASE:1.5
	netbsd-10-0-RC6:1.5
	netbsd-10-0-RC5:1.5
	netbsd-10-0-RC4:1.5
	netbsd-10-0-RC3:1.5
	netbsd-10-0-RC2:1.5
	netbsd-10-0-RC1:1.5
	netbsd-10:1.5.0.72
	netbsd-10-base:1.5
	netbsd-9-3-RELEASE:1.5
	cjep_sun2x-base1:1.5
	cjep_sun2x:1.5.0.70
	cjep_sun2x-base:1.5
	cjep_staticlib_x-base1:1.5
	netbsd-9-2-RELEASE:1.5
	cjep_staticlib_x:1.5.0.68
	cjep_staticlib_x-base:1.5
	netbsd-9-1-RELEASE:1.5
	phil-wifi-20200421:1.5
	phil-wifi-20200411:1.5
	is-mlppp:1.5.0.66
	is-mlppp-base:1.5
	phil-wifi-20200406:1.5
	netbsd-8-2-RELEASE:1.5
	netbsd-9-0-RELEASE:1.5
	netbsd-9-0-RC2:1.5
	netbsd-9-0-RC1:1.5
	phil-wifi-20191119:1.5
	netbsd-9:1.5.0.64
	netbsd-9-base:1.5
	phil-wifi-20190609:1.5
	netbsd-8-1-RELEASE:1.5
	netbsd-8-1-RC1:1.5
	pgoyette-compat-merge-20190127:1.5
	pgoyette-compat-20190127:1.5
	pgoyette-compat-20190118:1.5
	pgoyette-compat-1226:1.5
	pgoyette-compat-1126:1.5
	pgoyette-compat-1020:1.5
	pgoyette-compat-0930:1.5
	pgoyette-compat-0906:1.5
	netbsd-7-2-RELEASE:1.5
	pgoyette-compat-0728:1.5
	netbsd-8-0-RELEASE:1.5
	phil-wifi:1.5.0.62
	phil-wifi-base:1.5
	pgoyette-compat-0625:1.5
	netbsd-8-0-RC2:1.5
	pgoyette-compat-0521:1.5
	pgoyette-compat-0502:1.5
	pgoyette-compat-0422:1.5
	netbsd-8-0-RC1:1.5
	pgoyette-compat-0415:1.5
	pgoyette-compat-0407:1.5
	pgoyette-compat-0330:1.5
	pgoyette-compat-0322:1.5
	pgoyette-compat-0315:1.5
	netbsd-7-1-2-RELEASE:1.5
	pgoyette-compat:1.5.0.60
	pgoyette-compat-base:1.5
	netbsd-7-1-1-RELEASE:1.5
	matt-nb8-mediatek:1.5.0.58
	matt-nb8-mediatek-base:1.5
	perseant-stdc-iso10646:1.5.0.56
	perseant-stdc-iso10646-base:1.5
	netbsd-8:1.5.0.54
	netbsd-8-base:1.5
	prg-localcount2-base3:1.5
	prg-localcount2-base2:1.5
	prg-localcount2-base1:1.5
	prg-localcount2:1.5.0.52
	prg-localcount2-base:1.5
	pgoyette-localcount-20170426:1.5
	bouyer-socketcan-base1:1.5
	pgoyette-localcount-20170320:1.5
	netbsd-7-1:1.5.0.50
	netbsd-7-1-RELEASE:1.5
	netbsd-7-1-RC2:1.5
	netbsd-7-nhusb-base-20170116:1.5
	bouyer-socketcan:1.5.0.48
	bouyer-socketcan-base:1.5
	pgoyette-localcount-20170107:1.5
	netbsd-7-1-RC1:1.5
	pgoyette-localcount-20161104:1.5
	netbsd-7-0-2-RELEASE:1.5
	localcount-20160914:1.5
	netbsd-7-nhusb:1.5.0.46
	netbsd-7-nhusb-base:1.5
	pgoyette-localcount-20160806:1.5
	pgoyette-localcount-20160726:1.5
	pgoyette-localcount:1.5.0.44
	pgoyette-localcount-base:1.5
	netbsd-7-0-1-RELEASE:1.5
	netbsd-7-0:1.5.0.42
	netbsd-7-0-RELEASE:1.5
	netbsd-7-0-RC3:1.5
	netbsd-7-0-RC2:1.5
	netbsd-7-0-RC1:1.5
	netbsd-5-2-3-RELEASE:1.5
	netbsd-5-1-5-RELEASE:1.5
	netbsd-6-0-6-RELEASE:1.5
	netbsd-6-1-5-RELEASE:1.5
	netbsd-7:1.5.0.40
	netbsd-7-base:1.5
	yamt-pagecache-base9:1.5
	yamt-pagecache-tag8:1.5
	netbsd-6-1-4-RELEASE:1.5
	netbsd-6-0-5-RELEASE:1.5
	tls-earlyentropy:1.5.0.38
	tls-earlyentropy-base:1.5
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.5
	riastradh-drm2-base3:1.5
	netbsd-6-1-3-RELEASE:1.5
	netbsd-6-0-4-RELEASE:1.5
	netbsd-5-2-2-RELEASE:1.5
	netbsd-5-1-4-RELEASE:1.5
	netbsd-6-1-2-RELEASE:1.5
	netbsd-6-0-3-RELEASE:1.5
	netbsd-5-2-1-RELEASE:1.5
	netbsd-5-1-3-RELEASE:1.5
	netbsd-6-1-1-RELEASE:1.5
	riastradh-drm2-base2:1.5
	riastradh-drm2-base1:1.5
	riastradh-drm2:1.5.0.32
	riastradh-drm2-base:1.5
	netbsd-6-1:1.5.0.36
	netbsd-6-0-2-RELEASE:1.5
	netbsd-6-1-RELEASE:1.5
	netbsd-6-1-RC4:1.5
	netbsd-6-1-RC3:1.5
	agc-symver:1.5.0.34
	agc-symver-base:1.5
	netbsd-6-1-RC2:1.5
	netbsd-6-1-RC1:1.5
	yamt-pagecache-base8:1.5
	netbsd-5-2:1.5.0.30
	netbsd-6-0-1-RELEASE:1.5
	yamt-pagecache-base7:1.5
	netbsd-5-2-RELEASE:1.5
	netbsd-5-2-RC1:1.5
	matt-nb6-plus-nbase:1.5
	yamt-pagecache-base6:1.5
	netbsd-6-0:1.5.0.28
	netbsd-6-0-RELEASE:1.5
	netbsd-6-0-RC2:1.5
	tls-maxphys:1.5.0.26
	tls-maxphys-base:1.5
	matt-nb6-plus:1.5.0.24
	matt-nb6-plus-base:1.5
	netbsd-6-0-RC1:1.5
	yamt-pagecache-base5:1.5
	yamt-pagecache-base4:1.5
	netbsd-6:1.5.0.22
	netbsd-6-base:1.5
	netbsd-5-1-2-RELEASE:1.5
	netbsd-5-1-1-RELEASE:1.5
	yamt-pagecache-base3:1.5
	yamt-pagecache-base2:1.5
	yamt-pagecache:1.5.0.4
	yamt-pagecache-base:1.5
	cherry-xenmp:1.5.0.20
	cherry-xenmp-base:1.5
	bouyer-quota2-nbase:1.5
	bouyer-quota2:1.5.0.18
	bouyer-quota2-base:1.5
	matt-mips64-premerge-20101231:1.5
	matt-nb5-mips64-premerge-20101231:1.5
	matt-nb5-pq3:1.5.0.16
	matt-nb5-pq3-base:1.5
	netbsd-5-1:1.5.0.14
	netbsd-5-1-RELEASE:1.5
	netbsd-5-1-RC4:1.5
	matt-nb5-mips64-k15:1.5
	netbsd-5-1-RC3:1.5
	netbsd-5-1-RC2:1.5
	netbsd-5-1-RC1:1.5
	netbsd-5-0-2-RELEASE:1.5
	matt-nb5-mips64-premerge-20091211:1.5
	matt-premerge-20091211:1.5
	matt-nb5-mips64-u2-k2-k4-k7-k8-k9:1.5
	matt-nb4-mips64-k7-u2a-k9b:1.5
	matt-nb5-mips64-u1-k1-k5:1.5
	matt-nb5-mips64:1.5.0.12
	netbsd-5-0-1-RELEASE:1.5
	jym-xensuspend-nbase:1.5
	netbsd-5-0:1.5.0.10
	netbsd-5-0-RELEASE:1.5
	netbsd-5-0-RC4:1.5
	netbsd-5-0-RC3:1.5
	netbsd-5-0-RC2:1.5
	jym-xensuspend:1.5.0.8
	jym-xensuspend-base:1.5
	netbsd-5-0-RC1:1.5
	netbsd-5:1.5.0.6
	netbsd-5-base:1.5
	matt-mips64-base2:1.5
	matt-mips64:1.4.0.20
	netbsd-4-0-1-RELEASE:1.4
	wrstuden-revivesa-base-3:1.5
	wrstuden-revivesa-base-2:1.5
	wrstuden-fixsa-newbase:1.4
	wrstuden-revivesa-base-1:1.5
	yamt-pf42-base4:1.5
	yamt-pf42-base3:1.5
	hpcarm-cleanup-nbase:1.5
	yamt-pf42-baseX:1.4
	yamt-pf42-base2:1.5
	wrstuden-revivesa:1.5.0.2
	wrstuden-revivesa-base:1.5
	yamt-pf42:1.4.0.18
	yamt-pf42-base:1.4
	keiichi-mipv6:1.4.0.16
	keiichi-mipv6-base:1.4
	matt-armv6-nbase:1.4
	matt-armv6-prevmlocking:1.4
	wrstuden-fixsa-base-1:1.4
	netbsd-4-0:1.4.0.14
	netbsd-4-0-RELEASE:1.4
	cube-autoconf:1.4.0.12
	cube-autoconf-base:1.4
	netbsd-4-0-RC5:1.4
	netbsd-4-0-RC4:1.4
	netbsd-4-0-RC3:1.4
	netbsd-4-0-RC2:1.4
	netbsd-4-0-RC1:1.4
	matt-armv6:1.4.0.10
	matt-armv6-base:1.4
	matt-mips64-base:1.4
	hpcarm-cleanup:1.4.0.8
	hpcarm-cleanup-base:1.4
	wrstuden-fixsa:1.4.0.6
	wrstuden-fixsa-base:1.4
	abandoned-netbsd-4-base:1.4
	abandoned-netbsd-4:1.4.0.2
	netbsd-4:1.4.0.4
	netbsd-4-base:1.4;
locks; strict;
comment	@# @;


1.5
date	2008.04.30.13.10.52;	author martin;	state Exp;
branches;
next	1.4;

1.4
date	2006.07.21.00.29.23;	author perseant;	state Exp;
branches
	1.4.18.1;
next	1.3;

1.3
date	2006.04.27.22.37.54;	author perseant;	state Exp;
branches;
next	1.2;

1.2
date	2006.04.22.00.10.55;	author perseant;	state Exp;
branches;
next	1.1;

1.1
date	2006.04.17.20.02.35;	author perseant;	state Exp;
branches;
next	;

1.4.18.1
date	2008.05.18.12.30.47;	author yamt;	state Exp;
branches;
next	;


desc
@@


1.5
log
@Convert TNF licenses to new 2 clause variant
@
text
@#!/usr/pkg/bin/perl
#
#	$NetBSD: check-all,v 1.4 2006/07/21 00:29:23 perseant Exp $
#
# Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
# by Konrad E. Schroder <perseant@@hhhh.org>.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

#
# Use dumplfs to find all locations of the Ifile inode on a given disk.
# Order these by serial number and call fsck_lfs on the raw disk for each.
# If any fsck gives errors (any line of all capital letters, with a few
# exceptions) print an error code with the daddr of the failing Ifile inode
# location.
#

$| = 1;
$rdev = $ARGV[0];
$gfile = $ARGV[1];
$wfile = $ARGV[2];
$sstart = $ARGV[3];
$test_rfw = 1; # $ARGV[4];
$rollid = 0;
open(DUMPLFS, "dumplfs $rdev |");

# Look for "roll_id" so we don't use garbage
while (<DUMPLFS>) {
	if ($ssize == 0 && m/ssize *([0-9]*)/) {
		$ssize = $1;
	}
	if ($fsize == 0 && m/fsize *([0-9]*)/) {
		$fsize = $1;
	}
	if (m/roll_id *([x0-9a-f]*)/) {
		$rollid = $1;
		last;
	}
}

# Now look for inodes and segment summaries.  Build a hash table of these
# based on serial number.  Ignore any with serial numbers lower than $sstart.

%iloc = ();
%snloc = ();
%sumloc = ();
print "Reading segments:";
while (<DUMPLFS>) {
	if (m/roll_id *([0-9a-f]*)/) {
		# print "rollid $1\n";
		if ("0x$1" ne $rollid) {
			# Skip the rest of this segment
			print "{skip bad rollid 0x$1}";
			while(<DUMPLFS>) {
				last if m/SEGMENT/;
			}
			# Fall through
		}
	}
	if (m/roll_id.*serial *([0-9]*)/) {
		$serno = $1;
		$snloc{$serno} = $segnum;
		$sumloc{$serno} = $sumloc;
		print "($serno)";
		if ($serno < $sstart) {
			# Skip the rest of this partial segment
			#print "{skip bad serno $serno}";
			while(<DUMPLFS>) {
				last if m/Segment Summary/ ||
					m/SEGMENT/;
			}
			# Fall through
		}
	}
	if (m/Segment Summary Info at 0x([0-9a-f]*)/) {
		$sumloc = $1;
		next;
	}
	if (m/0x([0-9a-f]*)/) {
		foreach $ss (split "0x", $_) {
			if ($ss =~ m/^([0-9a-f][0-9a-f]*)/) {
				# print "iblk 0x$1\n";
				$daddr = $1;
				if (m/[^0-9]1v1/) {
					# print "** ifblk 0x$daddr\n";
					$iloc{$serno} = $daddr;
					$lastaddr = $daddr;
				}
			}
		}
	}
	if (m/SEGMENT *([0-9]*)/) {
		$segnum = $1;
		print "[$segnum]";
	}
}
print "\n";
close(DUMPLFS);

# Complain about missing partial-segments
for ($i = $sstart; $i < $serno; ++$i) {
	if (hex $sumloc{$i} == 0 && $i > 0) {
		print "Oops, couldn't find pseg $i\n";
	}
}

# If there were no checkpoints, print *something*
if ($#iloc == 0) {
	print "0 $sstart 0\n";
	exit 0;
}

#
# Now fsck each checkpoint in turn, beginning with $sstart.
# Because the log wraps we will have to reconstruct the filesystem image
# as it existed at each checkpoint before running fsck.
#
# Look for lines containing only caps or "!", but ignore known
# false positives.
#
$error = 0;
$lastgood = $sstart - 1;
open(LOG, ">>check-all.log");
print "Available checkpoints:";
print LOG "Available checkpoints:";
foreach $k (sort { $a <=> $b } keys %iloc) {
	$a = $iloc{$k};
	print " $a";
	print LOG " $a";
}
print "\n";
print LOG "\n";

#
# Copy the partial segments $_[0]--$_[1] from the raw device onto
# the working file.  Return the next partial-segment serial number
# after the last one we copied (usually $_[1] + 1, except in case of
# an error).
#
sub copypseg
{
	my ($blstart, $blstop, $segstop, $cmd);
	my ($totalstart, $totalstop);

	$totalstart = 0;
	$totalstop = 0;
	for ($i = $_[0]; $i <= $_[1]; ++$i) {
		$blstart = hex $sumloc{$i};
		last if $blstart <= 0;
		$totalstart = $blstart if $totalstart == 0;
		$blstop = hex $sumloc{$i + 1};
		$segstop = ((int ($blstart / $fps)) + 1) * $fps;
		if ($segstop < $blstop || $blstop < $blstart) {
			#print "Adjusting $blstop -> $segstop\n";
			$blstop = $segstop;
		}
		$totalstop = $blstop;

		print "pseg $i: write blocks ", hex $blstart, "-", hex ($blstop - 1), "\n";
		$blstart = $blstop;
	}
	$cmd = "dd if=$rdev of=$wfile bs=$fsize seek=$totalstart " .
		"skip=$totalstart conv=notrunc count=" .
		($totalstop - $totalstart);
#	print "$cmd\n";
	system("$cmd >/dev/null 2>&1");

	return $i;
}

print "Recreating filesystem image as of $sstart:\n";
if ($sstart == 0) {
	$cmd = "dd if=$rdev of=$wfile bs=1m conv=swab,oldebcdic"; # garbage
} else {
	$cmd = "dd if=$gfile of=$wfile bs=1m";
}
print "$cmd\n";
system("$cmd >/dev/null 2>&1");

print "Copying over first superblock\n";
system("dd if=$rdev of=$wfile bs=8k count=2 conv=notrunc >/dev/null 2>&1");

sub test_fsck
{
	my $a = $_[0];
	my $flags = $_[1];
	my $printit = $_[2];
	my $output = "";

	$flags = "-n -f -i 0x$a $wfile" unless $flags;

	$cmd = "fsck_lfs $flags";
	print "$cmd\n";
	print LOG "$cmd\n";
	open(FSCK, "$cmd 2>&1 |");
	while(<FSCK>) {
		print LOG;
		$rline = "$_";
		chomp;

		# Known false positives (mismatch between sb and ifile,
		# which should be expected given we're using an arbitrarily
		# old version of the ifile)
		if (m/AVAIL GIVEN/ ||
		    m/BFREE GIVEN/ ||
		    m/DMETA GIVEN/ ||
		    m/NCLEAN GIVEN/ ||
		    m/FREE BUT NOT ON FREE LIST/ ||	# UNWRITTEN inodes OK
		    m/FILE SYSTEM WAS MODIFIED/ ||
		    m/FREE LIST HEAD IN SUPERBLOCK/ ) {
			next;
		}

		# Fsck reports errors in ALL CAPS
		# But don't count hex numbers as "lowercase".
		$oline = "$_";
		s/0x[0-9a-f]*//g;
		if (m/[A-Z]/ && ! m/[a-z]/) {
			$error = 1;
			$errsn = $k;
			$errstr = "1 $k 0x$a $oline";
			# last;
		}

		# Log everything we get, except for some things we
		# will see every single time.
		if (m/checkpoint invalid/ ||
		    m/skipping free list check/ ||
		    m/expect discrepancies/) {
			next;
		}
		$output .= $rline;
	}
	close(FSCK);

	if ($? != 0) {
		$error = 1;
		$errsn = $k;
		$errstr = "1 $k 0x$a <" . (hex $?) . ">";
	}

	if ($error || $printit) {
		print $output;
	}
}

$blstart = 0;
$fps = $ssize / $fsize;
$oind = ($sstart ? $sstart : 1);
BIGLOOP: foreach $k (sort { $a <=> $b } keys %iloc) {
	$a = $iloc{$k};

	if (hex($a) > hex($lastaddr)) {
		print "Skipping out-of-place checkpoint $k at $a\n";
		next;
	}

	if ($test_rfw && $iloc{$oind - 1}) {
		for ($tk = $oind; $tk < $k; $tk++) {
			print "Test roll-forward agent at non-checkpoint pseg $tk\n";
			print LOG "Test roll-forward agent at non-checkpoint pseg $tk\n";
			&copypseg($oind, $tk);
			# Add -d flag here for verbose debugging info
			$flags = "-p -f -i 0x" . $iloc{$oind - 1} . " $wfile";
			&test_fsck($iloc{$oind - 1}, $flags, 1);
			last BIGLOOP if $error;

			# note lack of -i flag, since the roll-forward
			# will have rewritten the superblocks.
			&test_fsck($iloc{$oind - 1}, "-n -f $wfile", 0);
			last BIGLOOP if $error;
		}
	}

	print "Recreate fs state at checkpoint pseg $k (from " . ($oind - 1) .
	      ")\n";
	$oind = &copypseg($oind, $k);

	&test_fsck($a, "", 0);

	last if $error;
	$lastgood = $k;	# record last good serial number
}

if ($errstr) {
	print "$errstr\n";
	exit 0;
}

if (!$errstr) {
	print "Bring filesystem state up to log wrap\n";
	$lastgood = &copypseg($oind, 100000000000) - 1;

	print "Copying this good image to $gfile\n";
	system("dd bs=1m if=$rdev of=$gfile >/dev/null 2>&1");
	print "0 $lastgood 0x$a\n";
	exit 0;
}

#
# Ifile write-checking paranoia.
#
# If we found an error, try to find which blocks of the Ifile inode changed
# between the last good checkpoint and this checkpoint; and which blocks
# *should* have changed.  This means (1) which segments were written; and
# (2) which inodes were written.  The 0 block of the Ifile should always
# have changed since lfs_avail is always in flux.
#

$cmd = "dumplfs";
$oseg = -1;
%iblk = ();
%iblk_done = ();
%why = ();
$iblk{0} = 1;
for ($i = $lastgood + 1; $i <= $errsn; $i++) {
	if ($oseg != $snloc{$i}) {
		$oseg = 0 + $snloc{$i};
		$cmd .= " -s$oseg";
	}
}
$cmd .= " $rdev";

open(DUMPLFS, "$cmd |");
while(<DUMPLFS>) {
	if (m/ifpb *([0-9]*)/) {
		$ifpb = $1;
	}
	if (m/sepb *([0-9]*)/) {
		$sepb = $1;
	}
	if (m/cleansz *([0-9]*)/) {
		$cleansz = $1;
	}
	if (m/segtabsz *([0-9]*)/) {
		$segtabsz = $1;
	}
	last if m/SEGMENT/;
}
while(<DUMPLFS>) {
	chomp;

	# Skip over partial segments outside our range of interest
	if (m/roll_id.*serial *([0-9]*)/) {
		$serno = $1;
		if ($serno <= $lastgood || $serno > $errsn) {
			# Skip the rest of this partial segment
			while(<DUMPLFS>) {
				last if m/Segment Summary/ || m/SEGMENT/;
			}
			next;
		}
	}

	# Look for inodes
	if (m/Inode addresses/) {
		s/^[^{]*{/ /o;
		s/}[^{]*$/ /o;
		s/}[^{]*{/,/og;
		s/v[0-9]*//og;
		@@ilist = split(',');
		foreach $i (@@ilist) {
			$i =~ s/ *//og;
			next if $i == 1;
			$iaddr = $cleansz + $segtabsz + int ($i / $ifpb);
			$iblk{$iaddr} = 1;
			$why{$iaddr} .= " $i";
		}
	}

	# Look for Ifile blocks actually written
	if (m/FINFO for inode: ([0-9]*) version/) {
		$i = $1;
		$inoblkmode = ($i == 1);
	}
	if ($inoblkmode && m/^[-\t 0-9]*$/) {
		s/\t/ /og;
		s/^ *//o;
		s/ *$//o;
		@@bn = split(' ');
		foreach $b (@@bn) {
			$iblk_done{$b} = 1;
		}
	}
}
close(DUMPLFS);

# Report found and missing Ifile blocks
print "Ifile blocks found:";
foreach $b (sort { $a <=> $b } keys %iblk) {
	if ($iblk_done{$b} == 1) {
		print " $b";
	}
}
print "\n";
	
print "Ifile blocks missing:";
foreach $b (sort { $a <=> $b } keys %iblk) {
	if ($iblk_done{$b} == 0) {
		$why{$b} =~ s/^ *//o;
		print " $b ($why{$b})";
	}
}
print "\n";

print "$errstr\n";
exit 0;
@


1.4
log
@Include testing of the roll-forward agent, when recreating the filesystem
partial-segment by partial-segment.  Each checkpoint should pass fsck_lfs -n
without errors; the results of fsck_lfs -p on non-checkpoints should also
pass fsck_lfs -n without errors.
@
text
@d3 1
a3 1
#	$NetBSD: check-all,v 1.3 2006/04/27 22:37:54 perseant Exp $
a18 7
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	This product includes software developed by the NetBSD
#	Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
@


1.4.18.1
log
@sync with head.
@
text
@d3 1
a3 1
#	$NetBSD: check-all,v 1.4 2006/07/21 00:29:23 perseant Exp $
d19 7
@


1.3
log
@Be a little more careful about what we copy into the working file when;
this takes care of another class of false positives.  Add copyright
assignments.
@
text
@d3 1
a3 1
#	$NetBSD: lfs.h,v 1.103 2006/04/17 20:02:34 perseant Exp $
d53 1
d189 1
a189 1
		print "pseg $i: write blocks $blstart-", $blstop - 1, "\n";
d213 6
a218 5
$blstart = 0;
$fps = $ssize / $fsize;
$oind = ($sstart ? $sstart : 1);
foreach $k (sort { $a <=> $b } keys %iloc) {
	$a = $iloc{$k};
d220 1
a220 4
	if (hex($a) > hex($lastaddr)) {
		print "Skipping out-of-place checkpoint $k at $a\n";
		next;
	}
d222 1
a222 4
	print "Recreate fs state at checkpoint pseg $k\n";
	$oind = &copypseg($oind, $k);

	$cmd = "fsck_lfs -n -f -i 0x$a $wfile";
d228 1
d239 1
d246 1
d251 2
a252 2
			$errstr = "1 $k 0x$a";
			last;
d254 9
d265 46
d314 6
d426 1
a426 1

@


1.2
log
@Regression test improvements:

Move the stop for LFCNWRAPSTOP to the point at which writing at segment 0
is really about to commence, since this is what the test expects (and
incidentally what a snapshotting utility wants as well).

More correctly reconstruct the on-disk state at every checkpoint, rather
than relying on the entire state at the point of wrapping to be accurate
(that is only true the first time we wrap).  Add a "make abort" target to
make rerunning the test more convenient when it has failed and we're done
analyzing the failure.
@
text
@d2 37
d43 3
a45 2
# If any fsck gives errors (lines containing "!", with a few exceptions)
# print an error code with the daddr of the failing Ifile inode location.
d82 1
d93 1
a93 1
		# print "serno $serno\n";
d96 1
d106 1
d123 1
a123 1
		print " $segnum";
d129 7
d163 37
d209 3
d214 1
d223 2
a224 13
	# Copy the balance of the "new" fs image over the old one.
	$blstop = int ((hex $a) / $fps) + 1;
	$blstop *= $fps;
	if ($blstop != $blstart) {
		$cmd = "dd if=$rdev of=$wfile bs=$fsize seek=$blstart " .
			"skip=$blstart conv=notrunc";
		if ($blstop) {
			$cmd .= " count=" . ($blstop - $blstart);
		}
		$blstart = $blstop;
		print "$cmd\n";
		system("$cmd >/dev/null 2>&1");
	}
d236 1
a236 1
		# old version fo the ifile)
d260 3
a262 1
$errstr = "0 $lastgood 0x$a" unless $errstr;
a263 1
if ($error == 0) {
d266 1
a266 1
	print "$errstr\n";
d271 2
@


1.1
log
@Introduce two fcntl calls that freeze the filesystem right at the point
where segment 0 is being considered for writing.  This allows for automated
checkpoint vailidity scanning, and could be used (in conjunction with the
existing LFCNREWIND) for e.g. snapshot dumps as well.

Include a regression test that does such scanning.

When writing the Ifile, loop through the dirty block list three times to
make sure that the checkpoint is always consistent (the first and second
times the Ifile blocks can cross a segment boundary; not so the third time
unless the segments are very small).  Discovered by using the aforementioned
regression test.
@
text
@d10 1
d12 3
a14 1
$sstart = $ARGV[1];
d20 6
d36 3
d47 1
a47 1
			next;
d50 1
a50 1
	if (m/serial *([0-9]*)/) {
d52 2
d58 2
a59 1
				last if m/Segment Summary/;
d61 1
a61 1
			next;
d64 3
d75 1
d80 3
a82 2
	if (m/SEGMENT/) {
		print;
d85 1
d88 6
d96 3
d103 1
d105 2
d109 43
a151 2
	print "fsck_lfs -n -f -i 0x$a $ARGV[0]\n";
	open(FSCK, "fsck_lfs -n -f -i 0x$a $ARGV[0] |");
d162 3
a164 1
		    m/NCLEAN GIVEN/) {
d173 2
a178 1
	print "$error $k 0x$a\n";
d180 30
d211 1
d213 79
a291 3
# If there were no checkpoints, print *something*
if ($#iloc == 0) {
	print "0 $sstart 0\n";
d293 4
@
