Subject: Solution(?) to kern/28804: quotacheck crashes on FFSv2
To: None <tech-userlevel@netbsd.org>
From: Edgar =?iso-8859-1?B?RnXf?= <efnbl06@bn2.maus.net>
List: tech-userlevel
Date: 02/13/2007 23:29:54
I don't know where this should belong. I already posted to tech-kern (sorry, by mistake I in fact posted it there twice), since the PR has originally been filed als kern/28804. Hovever, I think it's a userland problem with quotacheck(8), so I re-post it here.

Also, the PR (kern/28804) is more than two years old, so the people recorded as interested parties may no longer be active. I've replied to the PR, but probably no-one is going to read that unless I hint at it.

There seem to be at least two obvious bugs in quotacheck(8).
While comparing the source to fbd's version, I also noticed that fbd seems to have incorporated several enhancements, mostly by McKusick, thay may be worthwile to import. They deal with not accounting for either the accounting files themselves or snapshots and an optimisation regarding soft dependencies I don't understand.

The following patch corrects the two problems (not setting ino, using a superblock field for sizing a malloc before reading in the SB):

--- quotacheck.c.orig	2004-12-12 06:57:03.000000000 +0100
+++ quotacheck.c	2007-02-11 16:32:55.000000000 +0100
@@ -1,5 +1,3 @@
-/*	$NetBSD: quotacheck.c,v 1.36 2004/12/12 05:57:03 christos Exp $	*/
-
 /*
  * Copyright (c) 1980, 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -360,19 +358,9 @@
 	sync();
 	dev_bsize = 1;

 
-	cgp = malloc(sblock.fs_cgsize);
-	if (cgp == NULL) {
-		warn("%s: can't allocate %d bytes of cg space", fsname,
-		    sblock.fs_cgsize);
-		if (pid != NULL)
-			exit(1);
-		return 1;
-	}
-
 	for (i = 0; ; i++) {
 		if (sblock_try[i] == -1) {
 			warnx("%s: superblock not found", fsname);
-			free(cgp);
 			if (pid != NULL)
 				exit(1);
 			return 1;
@@ -411,10 +399,20 @@
 		break;
 	}

 
+	cgp = malloc(sblock.fs_cgsize);
+	if (cgp == NULL) {
+		warn("%s: can't allocate %d bytes of cg space", fsname,
+		    sblock.fs_cgsize);
+		if (pid != NULL)
+			exit(1);
+		return 1;
+	}
+
 	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
 	maxino = sblock.fs_ncg * sblock.fs_ipg;
-	for (ino = 0, cg = 0; cg < sblock.fs_ncg; cg++) {
-		setinodebuf(cg * sblock.fs_ipg);
+	for (cg = 0; cg < sblock.fs_ncg; cg++) {
+		ino = cg * sblock.fs_ipg;
+		setinodebuf(ino);
 #ifdef HAVE_UFSv2
 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
 			bread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)cgp,

Anyone to check/verify/confirm this?