Subject: bin/15449: fsck_ffs FS_42POSTBLFMT compatibility bug
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dbj@netbsd.org>
List: netbsd-bugs
Date: 01/31/2002 18:55:20
>Number:         15449
>Category:       bin
>Synopsis:       fsck_ffs FS_42POSTBLFMT compatibility bug
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 31 15:57:01 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Darrin B. Jewell
>Release:        NetBSD 1.5ZA 20020131
>Organization:
>Environment:
System: NetBSD quiteria 1.5ZA NetBSD 1.5ZA (QUITERIA) #1: Thu Jan 17 23:58:17 EST 2002 dbj@quiteria:/usr/src/sys/arch/macppc/compile/QUITERIA macppc
Architecture: powerpc
Machine: macppc
>Description:

fsck_ffs, when run on old filesystems that set FS_42POSTBLFMT,
will check the sblock->fs_interleave and sblock->fs_npsect fields,
for validity, even though these fields were not used by that
filesystem version.

>How-To-Repeat:
Try to fsck an old filesystem that sets FS_42POSTBLFMT.
>Fix:

Please review the following fix.  I plan to commit this patch unless I
get negative feedback.

Darrin

Index: pass5.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/pass5.c,v
retrieving revision 1.27
diff -u -r1.27 pass5.c
--- pass5.c	2001/08/17 02:18:47	1.27
+++ pass5.c	2002/01/31 23:43:23
@@ -64,6 +64,7 @@
 pass5()
 {
 	int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
+	int32_t savednpsect, savedinterleave;
 	int inomapsize, blkmapsize;
 	struct fs *fs = sblock;
 	ufs_daddr_t dbase, dmax;
@@ -136,7 +137,11 @@
 		inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
 		ocg->cg_magic = CG_MAGIC;
 		savednrpos = fs->fs_nrpos;
+		savednpsect = fs->fs_npsect;
+		savedinterleave = fs->fs_interleave;
 		fs->fs_nrpos = 8;
+		fs->fs_npsect = fs->fs_nsect;
+		fs->fs_interleave = 1;
 		break;
 
 	case FS_DYNAMICPOSTBLFMT:
@@ -409,8 +414,11 @@
                         cgdirty();
                 }
 	}
-	if (fs->fs_postblformat == FS_42POSTBLFMT)
+	if (fs->fs_postblformat == FS_42POSTBLFMT) {
 		fs->fs_nrpos = savednrpos;
+		fs->fs_npsect = savednpsect;
+		fs->fs_interleave = savedinterleave;
+	}
 	if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0) {
 		if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
 			memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
Index: setup.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/setup.c,v
retrieving revision 1.52
diff -u -r1.52 setup.c
--- setup.c	2001/12/19 10:05:20	1.52
+++ setup.c	2002/01/31 23:43:23
@@ -199,8 +199,9 @@
 			sbdirty();
 		}
 	}
-	if (sblock->fs_interleave < 1 || 
-	    sblock->fs_interleave > sblock->fs_nsect) {
+	if (sblock->fs_postblformat != FS_42POSTBLFMT &&
+	    (sblock->fs_interleave < 1 || 
+	    sblock->fs_interleave > sblock->fs_nsect)) {
 		pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK",
 			sblock->fs_interleave);
 		sblock->fs_interleave = 1;
@@ -211,8 +212,9 @@
 			dirty(&asblk);
 		}
 	}
-	if (sblock->fs_npsect < sblock->fs_nsect || 
-	    sblock->fs_npsect > sblock->fs_nsect*2) {
+	if (sblock->fs_postblformat != FS_42POSTBLFMT &&
+	    (sblock->fs_npsect < sblock->fs_nsect || 
+	    sblock->fs_npsect > sblock->fs_nsect*2)) {
 		pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK",
 			sblock->fs_npsect);
 		sblock->fs_npsect = sblock->fs_nsect;
@@ -324,6 +326,10 @@
 		doinglevel1++;
 		sblock->fs_postblformat = FS_DYNAMICPOSTBLFMT;
 		sblock->fs_nrpos = 8;
+		if (sblock->fs_npsect < sblock->fs_nsect)
+			sblock->fs_npsect = sblock->fs_nsect;
+		if (sblock->fs_interleave < 1)
+			sblock->fs_interleave = 1;
 		sblock->fs_postbloff =
 		    (char *)(&sblock->fs_opostbl[0][0]) -
 		    (char *)(&sblock->fs_firstfield);
>Release-Note:
>Audit-Trail:
>Unformatted: