NetBSD Problem Report #42350

From woods@once.weird.com  Fri Nov 20 05:42:30 2009
Return-Path: <woods@once.weird.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id CE6D563B844
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 20 Nov 2009 05:42:29 +0000 (UTC)
Message-Id: <m1NBKvS-001EJQC@once.weird.com>
Date: Thu, 19 Nov 2009 23:16:50 -0500 (EST)
From: "Greg A. Woods" <woods@planix.com>
Sender: "Greg A. Woods" <woods@once.weird.com>
Reply-To: "Greg A. Woods" <woods@planix.com>
To: gnats-bugs@gnats.NetBSD.org
Subject: frag size in "df -G" output has never been the right value, etc.
X-Send-Pr-Version: 3.95

>Number:         42350
>Category:       bin
>Synopsis:       frag size in "df -G" output has never been the right value, etc.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 20 05:45:00 +0000 2009
>Originator:     Greg A. Woods
>Release:        -current (2009/11/19)
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:
System: NetBSD current
>Description:

	running "df -G" to find out file system block and frag sizes
	revealed it wasn't reporting the correct numbers

	that leads me to another round of fixes to df(1)....

>How-To-Repeat:

	notice that "df -G" wasn't reporting correct frag size (due the
	fact my initial changes in PR# 36541 were against a revision
	prior to the conversion to statvfs(2), i.e. they work with
	statfs(), but not statvfs(), and when I suggested more changes
	against 1.77 in a later reply I did not catch this bug)

	notice that column headers were wrongly spaced

	notice a comment about nflag vs. old statfs() that can be fixed
	now with statvfs1()

	read the code again and notice serveral other problems, notably
	that most struct statvfs fields are unsigned, and thus the
	available blocks field can never go negative now either

>Fix:

Index: bin/df/df.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/bin/df/df.c,v
retrieving revision 1.86
diff -u -r1.86 df.c
--- bin/df/df.c	6 Jun 2009 09:30:45 -0000	1.86
+++ bin/df/df.c	20 Nov 2009 03:53:27 -0000
@@ -74,8 +74,8 @@
 void	 maketypelist(char *);
 long	 regetmntinfo(struct statvfs **, long);
 void	 usage(void);
-void	 prthumanval(int64_t, const char *);
-void	 prthuman(struct statvfs *, int64_t, int64_t);
+void	 prthumanval(uint64_t, const char *);
+void	 prthuman(struct statvfs *, uint64_t, uint64_t);
 const char *
 	strpct64(uint64_t, uint64_t, u_int);

@@ -181,11 +181,7 @@
 					mntpt = *argv;
 			} else
 				mntpt = *argv;
-			/*
-			 * Statfs does not take a `wait' flag, so we cannot
-			 * implement nflag here.
-			 */
-			if (!statvfs(mntpt, &mntbuf[mntsize]))
+			if (!statvfs1(mntpt, &mntbuf[mntsize], nflag ? ST_NOWAIT : 0))
 				if (lflag &&
 				    (mntbuf[mntsize].f_flag & MNT_LOCAL) == 0)
 					warnx("Warning: %s is not a local %s",
@@ -327,11 +323,16 @@
 }

 void
-prthumanval(int64_t bytes, const char *pad)
+prthumanval(uint64_t bytes, const char *pad) /* XXX passing pad as strings full
+					      * of spaces is unbelievably
+					      * bogus, but I'm not going to fix
+					      * it because the whole idea of
+					      * using/needing variable space
+					      * padding here is stupid */
 {
 	char buf[6];

-	(void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
+	(void)humanize_number(buf, sizeof(buf) - 1,
 	    bytes, "", HN_AUTOSCALE,
 	    HN_B | HN_NOSPACE | HN_DECIMAL);

@@ -339,22 +340,22 @@
 }

 void
-prthuman(struct statvfs *sfsp, int64_t used, int64_t bavail)
+prthuman(struct statvfs *sfsp, uint64_t used, uint64_t bavail)
 {

-	prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), "  ");
-	prthumanval((int64_t)(used * sfsp->f_frsize), "    ");
-	prthumanval((int64_t)(bavail * sfsp->f_frsize), "    ");
+	prthumanval((uint64_t)(sfsp->f_blocks * sfsp->f_frsize), "   ");
+	prthumanval((uint64_t)(used * sfsp->f_frsize), "    ");
+	prthumanval((uint64_t)(bavail * sfsp->f_frsize), "    ");
 }

 /*
  * Convert statvfs returned filesystem size into BLOCKSIZE units.
  * Attempts to avoid overflow for large filesystems.
  */
-#define fsbtoblk(num, fsbs, bs)					\
-	(((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ?	\
-	    (int64_t)(num) / (int64_t)((bs) / (fsbs)) :		\
-	    (int64_t)(num) * (int64_t)((fsbs) / (bs)))
+#define fsbtoblk(num, fsbs, bs)						\
+	(((fsbs) != 0 && (fsbs) < (bs)) ?				\
+	 (uint64_t)(num) / (uint64_t)((bs) / (uint64_t)(fsbs)) :	\
+	 (uint64_t)(num) * (uint64_t)((fsbs) / (uint64_t)(bs)))

 /*
  * Print out status about a filesystem.
@@ -367,16 +368,17 @@
 	static const char *header;
 	static const char full[] = "100%";
 	static const char empty[] = "  0%";
-	int64_t used, availblks, inodes;
-	int64_t bavail;
+	uint64_t used, availblks, inodes; /* xxx fsblkcnt_t & fsfilcnt_t ??? */
+	uint64_t bavail;

 	if (gflag) {
 		/*
-		 * From SunOS-5.6:
+		 * From SunOS-5.6 (Note the actual output does include spaces
+		 * at the ends of the lines! Don't remove them here!):
 		 *
-		 * /var               (/dev/dsk/c0t0d0s3 ):         8192 block size          1024 frag size
+		 * /var               (/dev/dsk/c0t0d0s3 ):         8192 block size          1024 frag size  
 		 *   984242 total blocks     860692 free blocks   859708 available         249984 total files
-		 *   248691 free files      8388611 filesys id
+		 *   248691 free files      8388611 filesys id  
 		 *      ufs fstype       0x00000004 flag             255 filename length
 		 *
 		 */
@@ -388,25 +390,25 @@
 					 * is of course the file
 					 * system's block size too.
 					 */
-		    sfsp->f_bsize);	/* not so surprisingly the
+		    sfsp->f_frsize);	/* not so surprisingly the
 					 * "fundamental file system
 					 * block size" is the frag
 					 * size.
 					 */
-		(void)printf("%10" PRId64 " total blocks %10" PRId64
-		    " free blocks  %10" PRId64 " available\n",
+		(void)printf("%10" PRIu64 " total blocks %10" PRIu64
+		    " free blocks  %10" PRIu64 " available\n",
 		    (uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree,
 		    (uint64_t)sfsp->f_bavail);
-		(void)printf("%10" PRId64 " total files  %10" PRId64
+		(void)printf("%10" PRIu64 " total files  %10" PRIu64
 		    " free files %12lx filesys id\n",
 		    (uint64_t)sfsp->f_ffree, (uint64_t)sfsp->f_files,
 		    sfsp->f_fsid);
 		(void)printf("%10s fstype  %#15lx flag  %17ld filename "
 		    "length\n", sfsp->f_fstypename, sfsp->f_flag,
 		    sfsp->f_namemax);
-		(void)printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64
+		(void)printf("%10lu owner %17" PRIu64 " syncwrites %12" PRIu64
 		    " asyncwrites\n\n", (unsigned long)sfsp->f_owner,
-		    sfsp->f_syncwrites, sfsp->f_asyncwrites);
+		    (uint64_t)sfsp->f_syncwrites, (uint64_t)sfsp->f_asyncwrites);

 		/*
 		 * a concession by the structured programming police to the
@@ -452,11 +454,11 @@
 			    "Mounted on\n", header);
 		} else {
 			(void)printf("%-*.*s %s       Used      Avail %%Cap",
-			    maxwidth - (headerlen - 9),
-			    maxwidth - (headerlen - 9),
+			    maxwidth - (headerlen - 10),
+			    maxwidth - (headerlen - 10),
 			    "Filesystem", header);
 			if (iflag)
-				(void)printf("    iUsed   iAvail %%iCap");
+				(void)printf("    iUsed  iAvail %%iCap");
 			(void)printf(" Mounted on\n");
 		}
 	}
@@ -471,7 +473,7 @@
 		 * <space used>, <space free>, <percentage used>,
 		 * <file system root>
 		 */
-		(void)printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s %s\n",
+		(void)printf("%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %s %s\n",
 		    sfsp->f_mntfromname,
 		    fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
 		    fsbtoblk(used, sfsp->f_frsize, blocksize),
@@ -492,7 +494,7 @@
 	if (hflag)
 		prthuman(sfsp, used, bavail);
 	else
-		(void)printf("%10" PRId64 " %10" PRId64 " %10" PRId64,
+		(void)printf("%10" PRIu64 " %10" PRIu64 " %10" PRIu64,
 		    fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize),
 		    fsbtoblk(used, sfsp->f_frsize, blocksize),
 		    fsbtoblk(bavail, sfsp->f_frsize, blocksize));
@@ -503,8 +505,8 @@
 	if (iflag) {
 		inodes = sfsp->f_files;
 		used = inodes - sfsp->f_ffree;
-		(void)printf(" %8jd %8jd %4s",
-		    (intmax_t)used, (intmax_t)sfsp->f_ffree,
+		(void)printf(" %8" PRIu64 " %8" PRIu64 " %4s",
+		    (uint64_t)used, (uint64_t)sfsp->f_ffree,
 		    inodes == 0 ? (used == 0 ? empty : full) :
 		    strpct64((uint64_t)used, (uint64_t)inodes, 0));
 	}

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.