Subject: Problem with df(1)
To: 'port-i386@netbsd.org' <port-i386@NetBSD.ORG>
From: Gunnar Helliesen <gunnar@bitcon.no>
List: port-i386
Date: 11/04/1997 18:14:15
Some of you might remember that I reported a problem with df(1) a while
back. The problem is that the free space calculations are wrong on large
disks:

atlas:~# df /dev/sd2c
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
/dev/sd2c    21952751 20433937 -41430858   -97%    /usr/local/ftp/.4

Perry E. Metzger suggested:

> Its obviously a type screw -- off_t's are probably not being used...

Being of the optimistic kind I set out to fix it myself. I found that df
uses the struct statfs(2) to get filesystem info, but that's how far I
got. Changing the definitions to unsigned in df.c and <sys/mount.h> and
building a new kernel and df didn't help much, so now I'm stuck.

As far as I can tell, this is where df.c calculates and prints the
filesystem info:

void    
prtstat(sfsp, maxwidth)
        struct statfs *sfsp; 
        int maxwidth;
{ 
        static long blocksize;
        static int headerlen, timesthrough;
        static char *header;
        long used, availblks, inodes; 
 
        if (maxwidth < 11) 
                maxwidth = 11;
        if (++timesthrough == 1) {
                if (kflag) {
                        blocksize = 1024;
                        header = "1K-blocks";
                        headerlen = strlen(header);
                } else
                        header = getbsize(&headerlen, &blocksize);
                (void)printf("%-*.*s %s     Used    Avail Capacity",
                    maxwidth, maxwidth, "Filesystem", header);
                if (iflag)
                        (void)printf(" iused   ifree  %%iused"); 
                (void)printf("  Mounted on\n");
        }
        (void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
        used = sfsp->f_blocks - sfsp->f_bfree;
        availblks = sfsp->f_bavail + used;
        (void)printf(" %*ld %8ld %8ld", headerlen,
            fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
            fsbtoblk(used, sfsp->f_bsize, blocksize),
            fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize));
        (void)printf(" %5.0f%%",
            availblks == 0 ? 100.0 : (double)used / (double)availblks *
100.0);
        if (iflag) {
                inodes = sfsp->f_files;
                used = inodes - sfsp->f_ffree;
                (void)printf(" %7ld %7ld %5.0f%% ", used, sfsp->f_ffree,
                   inodes == 0 ? 100.0 : (double)used / (double)inodes *
100.0);
        } else
                (void)printf("  ");
        (void)printf("  %s\n", sfsp->f_mntonname);
}


My question is: Where are the elements of statfs calculated in the first
place? How many places are the numbers passed as signed? Am I even on
the right track? ;-)

Help anyone?

Gunnar

--
Gunnar Helliesen   | Bergen IT Consult AS  | NetBSD/VAX on a uVAX II
Systems Consultant | Bergen, Norway        | '86 Jaguar Sovereign 4.2
gunnar@bitcon.no   | http://www.bitcon.no/ | '73 Mercedes 280 (240D)