Project

General

Profile

Bug #7178

Updated by Andrew Stormont over 4 years ago

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: 

 <pre> 
 # 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 
 </pre> 

 The fix is simple one-line change (minus the copyright): 

 <pre> 
 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 
 </pre> 

 Edit: 

 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.

Back