tmpfs incorrectly calculates amount of free space
There is a flaw in the algorithm tmpfs uses to calculate available space. It assumes that tm_anonmax is always more than tm_anonmem and this is not always the case, for example, when remounting a full tmpfs filesystem with a smaller "size". The filesystem is full but statvfs reports that all memory is available. See in the example below how the capacity actually increases:
# df -h /tmp/ Filesystem Size Used Available Capacity Mounted on swap 1.0G 903M 121M 89% /tmp # mount -o remount,size=512m /tmp # df -h /tmp/ Filesystem Size Used Available Capacity Mounted on swap 32G 903M 31G 3% /tmp # mount -o remount,size=1024m /tmp # df -h /tmp/ Filesystem Size Used Available Capacity Mounted on swap 1.0G 903M 121M 89% /tmp
The fix is simple one-line change (minus the copyright):
diff --git a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c index f22cc3e..1611d63 100644 --- a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c +++ b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright 2016 RackTop Systems. */ #include <sys/types.h> @@ -589,7 +590,7 @@ tmp_statvfs(struct vfs *vfsp, struct statvfs64 *sbp) * If tm_anonmax for this mount is less than the available swap space * (minus the amount tmpfs can't use), use that instead */ - if (blocks > tmpfs_minfree) + if (blocks > tmpfs_minfree && tm->tm_anonmax > tm->tm_anonmem) sbp->f_bfree = MIN(blocks - tmpfs_minfree, tm->tm_anonmax - tm->tm_anonmem); else
There are also issues with the way f_free and f_files are calculated. Both values should be based on tm_anonmax but this isn't the case currently.