Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Nov 2008 23:42:49 +0100
From:      Max Laier <max@love2party.net>
To:        freebsd-hackers@freebsd.org
Cc:        lhmwzy@gmail.com, koitsu@freebsd.org, pjd@freebsd.org, Giorgos Keramidas <keramida@freebsd.org>, Pete French <petefrench@ticketswitch.com>
Subject:   Re: du -A / -B options [Re: zfs quota question]
Message-ID:  <200811042342.49827.max@love2party.net>
In-Reply-To: <200811012114.43137.max@love2party.net>
References:  <E1KnA2b-0007ls-8u@dilbert.ticketswitch.com> <200810071314.45922.max@love2party.net> <200811012114.43137.max@love2party.net>

next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_p/MEJlOmDTp9+rV
Content-Type: text/plain;
  charset="iso-8859-15"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi again,

On Saturday 01 November 2008 21:14:42 I wrote:
> a thread on freebsd-stable@ [1] about problems with du(1) and compressed
> zfs filesystems got me looking for a possible solution.  Attached is a di=
ff
> for du(1) that adds two new options:
>
>  -A to display the apparent size of the file instead of the used blocks.
>  -B bsize to specify a custom blocksize.  In particular one <512byte
>
> The GNU du(1) has --apparent-size for -A, but we don't like long options.
> That's not to say that it couldn't be added for script compat. -B is
> probably not that interesting, but it can be helpful and came for free.

Attached is an updated patch.  This refines the -B option to something more=
=20
useful (and fixes a bug in the original patch).

=46rom the man page:

     -B blocksize
             Calculate block counts in blocksize byte blocks.  This is diff=
er-
             ent from the -k, -m options or setting BLOCKSIZE and gives an
             estimate of how many space the examined file hierachy would
             require on a filesystem with the given blocksize.  Unless in -A
             mode, blocksize is rounded up to the next multiple of 512.

I think this is also very helpful and came for almost free.  I made sure to=
=20
not loose any range in the calculations when not in -A mode.  In -A mode an=
d=20
with small -B values you obviously can blast the 2^63bit block counter in=20
struct fts earlier.

Please review, test & comment ... I plan to commit this in a few days if I=
=20
don't hear otherwise.  Thanks.

> Any objections against the general concept?  It's rather complicated to g=
et
> the apparent size of a directory hierarchy without scripting.  I often
> wonder if some hierarchy will fit on a CD/DVD and compressed zfs makes th=
is
> really difficult.
>
> As for the code, I know that there are a couple of style(9) errors in the=
re
> - mostly because the lines already exceeded 80 chars before my changes and
> I plan to clean that up before I commit - should there be enough support
> for the change itself.
>
> Thoughts?
>
> [1]
> http://lists.freebsd.org/pipermail/freebsd-stable/2008-October/045698.html

=2D-=20
/"\  Best regards,                      | mlaier@freebsd.org
\ /  Max Laier                          | ICQ #67774661
 X   http://pf4freebsd.love2party.net/  | mlaier@EFnet
/ \  ASCII Ribbon Campaign              | Against HTML Mail and News

--Boundary-00=_p/MEJlOmDTp9+rV
Content-Type: text/plain;
  charset="iso-8859-15";
  name="du.AB.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="du.AB.diff"

Index: du.1
===================================================================
--- du.1	(revision 184563)
+++ du.1	(working copy)
@@ -40,11 +40,12 @@
 .Nd display disk usage statistics
 .Sh SYNOPSIS
 .Nm
+.Op Fl A
 .Op Fl H | L | P
 .Op Fl a | s | d Ar depth
 .Op Fl c
 .Op Fl l
-.Op Fl h | k | m
+.Op Fl h | k | m | B Ar blocksize
 .Op Fl n
 .Op Fl x
 .Op Fl I Ar mask
@@ -60,6 +61,25 @@
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl A
+Display the apparent size instead of the disk usage.
+This can be helpful when operating on compressed volumes or sparse files.
+.It Fl B Ar blocksize
+Calculate block counts in
+.Ar blocksize
+byte blocks.
+This is different from the
+.Fl k, m
+options or setting
+.Ev BLOCKSIZE
+and gives an estimate of how many space the examined file hierachy would
+require on a filesystem with the given
+.Ar blocksize .
+Unless in
+.Fl A
+mode,
+.Ar blocksize
+is rounded up to the next multiple of 512.
 .It Fl H
 Symbolic links on the command line are followed, symbolic links in file
 hierarchies are not followed.
@@ -136,14 +156,19 @@
 If the environment variable
 .Ev BLOCKSIZE
 is set, and the
-.Fl k
-option is not specified, the block counts will be displayed in units of that
-size block.
+.Fl k, m
+or
+.Fl h
+options are not specified, the block counts will be displayed in units of
+that size block.
 If
 .Ev BLOCKSIZE
 is not set, and the
-.Fl k
-option is not specified, the block counts will be displayed in 512-byte blocks.
+.Fl k, m
+or
+.Fl h
+options are not specified, the block counts will be displayed in 512-byte
+blocks.
 .El
 .Sh SEE ALSO
 .Xr df 1 ,
Index: du.c
===================================================================
--- du.c	(revision 184656)
+++ du.c	(working copy)
@@ -79,14 +79,15 @@
 static int	ignorep(FTSENT *);
 
 static int	nodumpflag = 0;
+static int	Aflag;
+static long	blocksize, cblocksize;
 
 int
 main(int argc, char *argv[])
 {
 	FTS		*fts;
 	FTSENT		*p;
-	off_t		savednumber;
-	long		blocksize;
+	off_t		savednumber, curblocks;
 	int		ftsoptions;
 	int		listall;
 	int		depth;
@@ -98,16 +99,30 @@
 	setlocale(LC_ALL, "");
 
 	Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag =
-	    lflag = 0;
+	    lflag = Aflag = 0;
 
 	save = argv;
 	ftsoptions = 0;
 	savednumber = 0;
+	cblocksize = DEV_BSIZE;
+	blocksize = 0;
 	depth = INT_MAX;
 	SLIST_INIT(&ignores);
 
-	while ((ch = getopt(argc, argv, "HI:LPasd:chklmnrx")) != -1)
+	while ((ch = getopt(argc, argv, "AB:HI:LPasd:chklmnrx")) != -1)
 		switch (ch) {
+		case 'A':
+			Aflag = 1;
+			break;
+		case 'B':
+			errno = 0;
+			cblocksize = atoi(optarg);
+			if (errno == ERANGE || cblocksize < 0) {
+				warnx("invalid argument to option B: %s",
+				    optarg);
+				usage();
+			}
+			break;
 		case 'H':
 			Hflag = 1;
 			break;
@@ -144,22 +159,18 @@
 			cflag = 1;
 			break;
 		case 'h':
-			if (setenv("BLOCKSIZE", "512", 1) == -1)
-				warn("setenv: cannot set BLOCKSIZE=512");
 			hflag = 1;
 			break;
 		case 'k':
 			hflag = 0;
-			if (setenv("BLOCKSIZE", "1024", 1) == -1)
-				warn("setenv: cannot set BLOCKSIZE=1024");
+			blocksize = 1024;
 			break;
 		case 'l':
 			lflag = 1;
 			break;
 		case 'm':
 			hflag = 0;
-			if (setenv("BLOCKSIZE", "1048576", 1) == -1)
-				warn("setenv: cannot set BLOCKSIZE=1048576");
+			blocksize = 1048576;
 			break;
 		case 'n':
 			nodumpflag = 1;
@@ -206,6 +217,9 @@
 	if (Pflag)
 		ftsoptions |= FTS_PHYSICAL;
 
+	if (!Aflag && (cblocksize % DEV_BSIZE) != 0)
+		cblocksize = howmany(cblocksize, DEV_BSIZE) * DEV_BSIZE;
+
 	listall = 0;
 
 	if (aflag) {
@@ -224,9 +238,14 @@
 		argv[1] = NULL;
 	}
 
-	(void)getbsize(&notused, &blocksize);
-	blocksize /= 512;
+	if (blocksize == 0)
+		(void)getbsize(&notused, &blocksize);
 
+	if (!Aflag) {
+		cblocksize /= DEV_BSIZE;
+		blocksize /= DEV_BSIZE;
+	}
+
 	rval = 0;
 
 	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
@@ -242,17 +261,19 @@
 			if (ignorep(p))
 				break;
 
+			curblocks = Aflag ?
+			    howmany(p->fts_statp->st_size, cblocksize) :
+			    howmany(p->fts_statp->st_blocks, cblocksize);
 			p->fts_parent->fts_bignum += p->fts_bignum +=
-			    p->fts_statp->st_blocks;
+			    curblocks;
 
 			if (p->fts_level <= depth) {
 				if (hflag) {
-					prthumanval(howmany(p->fts_bignum,
-					    blocksize));
+					prthumanval(p->fts_bignum);
 					(void)printf("\t%s\n", p->fts_path);
 				} else {
 					(void)printf("%jd\t%s\n",
-					    (intmax_t)howmany(p->fts_bignum,
+					    howmany(p->fts_bignum * cblocksize,
 					    blocksize), p->fts_path);
 				}
 			}
@@ -273,21 +294,22 @@
 			    linkchk(p))
 				break;
 
+			curblocks = Aflag ?
+			    howmany(p->fts_statp->st_size, cblocksize) :
+			    howmany(p->fts_statp->st_blocks, cblocksize);
+
 			if (listall || p->fts_level == 0) {
 				if (hflag) {
-					prthumanval(howmany(
-					    p->fts_statp->st_blocks,
-					    blocksize));
+					prthumanval(curblocks);
 					(void)printf("\t%s\n", p->fts_path);
 				} else {
 					(void)printf("%jd\t%s\n",
-					    (intmax_t)howmany(
-					    p->fts_statp->st_blocks,
-					    blocksize),	p->fts_path);
+					    howmany(curblocks * cblocksize,
+					    blocksize), p->fts_path);
 				}
 			}
 
-			p->fts_parent->fts_bignum += p->fts_statp->st_blocks;
+			p->fts_parent->fts_bignum += curblocks;
 		}
 		savednumber = p->fts_parent->fts_bignum;
 	}
@@ -297,11 +319,11 @@
 
 	if (cflag) {
 		if (hflag) {
-			prthumanval(howmany(savednumber, blocksize));
+			prthumanval(savednumber);
 			(void)printf("\ttotal\n");
 		} else {
 			(void)printf("%jd\ttotal\n", (intmax_t)howmany(
-			    savednumber, blocksize));
+			    savednumber * cblocksize, blocksize));
 		}
 	}
 
@@ -448,7 +470,9 @@
 {
 	char buf[5];
 
-	bytes *= DEV_BSIZE;
+	bytes *= cblocksize;
+	if (!Aflag)
+		bytes *= DEV_BSIZE;
 
 	humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE,
 	    HN_B | HN_NOSPACE | HN_DECIMAL);
@@ -460,8 +484,9 @@
 usage(void)
 {
 	(void)fprintf(stderr,
-		"usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] "
-		"[-l] [-h | -k | -m] [-n] [-x] [-I mask] [file ...]\n");
+		"usage: du [-A] [-H | -L | -P] [-a | -s | -d depth] [-c] "
+		"[-l] [-h | -k | -m | -B bsize] [-n] [-x] [-I mask] "
+		"[file ...]\n");
 	exit(EX_USAGE);
 }
 

--Boundary-00=_p/MEJlOmDTp9+rV--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811042342.49827.max>