statfs patch for minix v2 fs

Herbert Xu (herbert@gondor.apana.org.au)
Thu, 11 Dec 1997 11:03:38 +1100 (EST)


Hi:
The statfs for minix implementation in 2.1.72 is buggy. It needs the
following patch to give the correct count. For a disk image that demonstrates
the problem, please check out

http://greathan.apana.org.au/~herbert/kernel/miniximage.gz

You might also want to read the stuff at

http://www.debian.org/Bugs/db/13/13381.html

-- 
Debian GNU/Linux 1.3 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://greathan.apana.org.au/~herbert/
PGP Key: http://greathan.apana.org.au/~herbert/pubkey.txt
--
--- linux/fs/minix/bitmap.c.orig	Wed Dec 10 22:16:50 1997
+++ linux/fs/minix/bitmap.c	Thu Dec 11 08:25:57 1997
@@ -21,17 +21,31 @@
 
 static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
 
-static unsigned long count_free(struct buffer_head *map[], unsigned numblocks)
+static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
 {
 	unsigned i, j, sum = 0;
 	struct buffer_head *bh;
   
-	for (i=0; i<numblocks; i++) {
+	for (i=0; i<numblocks-1; i++) {
 		if (!(bh=map[i])) 
 			return(0);
 		for (j=0; j<BLOCK_SIZE; j++)
-			sum += nibblemap[bh->b_data[j] & 0xf] 
-				+ nibblemap[(bh->b_data[j]>>4)&0xf];
+			sum += nibblemap[bh->b_data[j] & 0xf]
+				+ nibblemap[(bh->b_data[j]>>4) & 0xf];
+	}
+
+	if (numblocks==0 || !(bh=map[numblocks-1]))
+		return(0);
+	i = (numbits-(numblocks-1)*BLOCK_SIZE*8)/8;
+	for (j=0; j<i; j++) {
+		sum += nibblemap[bh->b_data[j] & 0xf]
+			+ nibblemap[(bh->b_data[j]>>4) & 0xf];
+	}
+
+	i = numbits%8;
+	if (i!=0) {
+		i = bh->b_data[j] | ~((1<<i) - 1);
+		sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
 	}
 	return(sum);
 }
@@ -108,8 +122,9 @@
 
 unsigned long minix_count_free_blocks(struct super_block *sb)
 {
-	return (count_free(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks)
-		 << sb->u.minix_sb.s_log_zone_size);
+	return (count_free(sb->u.minix_sb.s_zmap, sb->u.minix_sb.s_zmap_blocks,
+		sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone + 1)
+		<< sb->u.minix_sb.s_log_zone_size);
 }
 
 static struct buffer_head *V1_minix_clear_inode(struct inode *inode)
@@ -266,5 +281,6 @@
 
 unsigned long minix_count_free_inodes(struct super_block *sb)
 {
-	return count_free(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks);
+	return count_free(sb->u.minix_sb.s_imap, sb->u.minix_sb.s_imap_blocks,
+		sb->u.minix_sb.s_ninodes + 1);
 }