zpl: Fix "df -i" to have better free inodes value
authorAndreas Dilger <adilger@whamcloud.com>
Fri, 16 Sep 2011 09:22:00 +0000 (03:22 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 28 Sep 2011 18:27:10 +0000 (11:27 -0700)
Due to the confusion in Linux statfs between f_frsize and f_bsize
the blocks counts were changed to be in units of z_max_blksize
instead of SPA_MINBLOCKSIZE as it is on other platforms.

However, the free files calculation in zfs_statvfs() is limited by
the free blocks count, since each dnode consumes one block/sector.
This provided a reasonable estimate of free inodes, but on Linux
this meant that the free inodes count was underestimated by a large
amount, since 256 512-byte dnodes can fit into a 128kB block, and
more if the max blocksize is increased to 1MB or larger.

Also, the use of SPA_MINBLOCKSIZE is semantically incorrect since
DNODE_SIZE may change to a value other than SPA_MINBLOCKSIZE and
may even change per dataset, and devices with large sectors setting
ashift will also use a larger blocksize.

Correct the f_ffree calculation to use (availbytes >> DNODE_SHIFT)
to more accurately compute the maximum number of dnodes that can
be created.

Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #413
Closes #400

module/zfs/zfs_vfsops.c

index 31692f4..0ee5413 100644 (file)
@@ -944,7 +944,7 @@ zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
         * For f_ffree, report the smaller of the number of object available
         * and the number of blocks (each object will take at least a block).
         */
-       statp->f_ffree = MIN(availobjs, statp->f_bfree);
+       statp->f_ffree = MIN(availobjs, availbytes >> DNODE_SHIFT);
        statp->f_files = statp->f_ffree + usedobjs;
        statp->f_fsid.val[0] = dentry->d_sb->s_dev;
        statp->f_fsid.val[1] = 0;