Subject: bin/35560: resize_ffs has been broken since the ffs2 import
To: None <,>
From: None <>
List: netbsd-bugs
Date: 02/07/2007 18:15:01
>Number:         35560
>Category:       bin
>Synopsis:       resize_ffs has been broken since the ffs2 import and won't even try to work with ffs1
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Feb 07 18:15:00 +0000 2007
>Originator:     Michael L. Hitch
>Release:        NetBSD 4.99.4
System: NetBSD 4.99.4 NetBSD 4.99.4 (GENERIC) #2: Sun Nov 26 15:36:46 MST 2006 amd64
Architecture: x86_64
Machine: amd64
	Resize_ffs used to work before the ffs2 import, and has never worked (even for
	ffs1 filesystems) since the import.

	I had tried it once quite a while ago, and figured something had changed
	in the ffs1 filesystem and required work in resize_ffs to fix.  Then
	recently I really wanted to be able to resize an ffs1 filesystem and
	looked into what was really happening.  I was able to determine what
	was broken and came up with a fix.  I still had problems, but that
	was probably due to trying to resize the root partition I booted from.
	I later had the chance to resize another ffs1 filesystem, and was
	successful doing that with my patch.
	Build sbin/resize_ffs (it's not normally built during a full build) and try
	running it on any ffs1 filesystem.  It complains about a ffs2 superblock.
	After the ffs2 import, changes were made to resize_ffs.c to allow it to
	build, but while the changes allow it to compile, they broke the old
	functionality.  The problem was that the old macros to define the
	superblock locations specified the location by block number, but the
	new macros specify the superblock by byte offset.

	This can be fixed in a couple of ways:  one would be to convert the
	byte offset to block in the loop that searches the possible superblock
	locations.  Another is to change the superblock read/write routines to
	take a byte offset, converting to a block number (which then gets
	converted back to a byte offset in the block read/write routines).

	I've used the second way:

Index: sbin/resize_ffs/resize_ffs.c
RCS file: /cvsroot/src/sbin/resize_ffs/resize_ffs.c,v
retrieving revision 1.8
diff -u -r1.8 resize_ffs.c
--- sbin/resize_ffs/resize_ffs.c	3 Jun 2005 03:34:44 -0000	1.8
+++ sbin/resize_ffs/resize_ffs.c	7 Feb 2007 16:05:43 -0000
@@ -1815,7 +1815,7 @@
 	int i;
-	writeat(where, newsb, SBLOCKSIZE);
+	writeat(where / DEV_BSIZE, newsb, SBLOCKSIZE);
 	for (i = 0; i < newsb->fs_ncg; i++) {
 		writeat(fsbtodb(newsb, cgsblock(newsb, i)), newsb, SBLOCKSIZE);
@@ -1841,7 +1841,7 @@
 	oldsb = (struct fs *) & sbbuf;
 	newsb = (struct fs *) (SBLOCKSIZE + (char *) &sbbuf);
 	for (where = search[i = 0]; search[i] != -1; where = search[++i]) {
-		readat(where, oldsb, SBLOCKSIZE);
+		readat(where / DEV_BSIZE, oldsb, SBLOCKSIZE);
 		if (oldsb->fs_magic == FS_UFS1_MAGIC)
 		if (where == SBLOCK_UFS2)