Print this page
7178 tmpfs incorrectly calculates amount of free space
Reviewed by: Alexander Stetsenko <astetsenko@racktopsystems.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
          +++ new/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 2011, Joyent, Inc. All rights reserved.
       24 + * Copyright 2016 RackTop Systems.
  24   25   */
  25   26  
  26   27  #include <sys/types.h>
  27   28  #include <sys/param.h>
  28   29  #include <sys/sysmacros.h>
  29   30  #include <sys/kmem.h>
  30   31  #include <sys/time.h>
  31   32  #include <sys/pathname.h>
  32   33  #include <sys/vfs.h>
  33   34  #include <sys/vfs_opreg.h>
↓ open down ↓ 545 lines elided ↑ open up ↑
 579  580  
 580  581          /*
 581  582           * Find the amount of available physical and memory swap
 582  583           */
 583  584          mutex_enter(&anoninfo_lock);
 584  585          ASSERT(k_anoninfo.ani_max >= k_anoninfo.ani_phys_resv);
 585  586          blocks = (ulong_t)CURRENT_TOTAL_AVAILABLE_SWAP;
 586  587          mutex_exit(&anoninfo_lock);
 587  588  
 588  589          /*
 589      -         * If tm_anonmax for this mount is less than the available swap space
 590      -         * (minus the amount tmpfs can't use), use that instead
 591      -         */
 592      -        if (blocks > tmpfs_minfree)
      590 +         * Compare the amount of space that should be free to this mount
      591 +         * (which may be limited by tm_anonmax) with the amount of space
      592 +         * that's actually free to all tmpfs and use the lowest value.
      593 +         */
      594 +        if (tm->tm_anonmax == ULONG_MAX)
      595 +                sbp->f_bfree = MAX(blocks - tmpfs_minfree, 0);
      596 +        else if (blocks > tmpfs_minfree && tm->tm_anonmax > tm->tm_anonmem)
 593  597                  sbp->f_bfree = MIN(blocks - tmpfs_minfree,
 594  598                      tm->tm_anonmax - tm->tm_anonmem);
 595  599          else
 596  600                  sbp->f_bfree = 0;
 597  601  
 598  602          sbp->f_bavail = sbp->f_bfree;
 599  603  
 600  604          /*
 601  605           * Total number of blocks is what's available plus what's been used
 602  606           */
↓ open down ↓ 16 lines elided ↑ open up ↑
 619  623                  pgcap = btop(cap);
 620  624                  pgused = btop(used);
 621  625  
 622  626                  sbp->f_bfree = MIN(pgcap - pgused, sbp->f_bfree);
 623  627                  sbp->f_bavail = sbp->f_bfree;
 624  628                  sbp->f_blocks = MIN(pgcap, sbp->f_blocks);
 625  629          }
 626  630  
 627  631          /*
 628  632           * The maximum number of files available is approximately the number
 629      -         * of tmpnodes we can allocate from the remaining kernel memory
 630      -         * available to tmpfs.  This is fairly inaccurate since it doesn't
 631      -         * take into account the names stored in the directory entries.
 632      -         */
 633      -        if (tmpfs_maxkmem > tmp_kmemspace)
 634      -                sbp->f_ffree = (tmpfs_maxkmem - tmp_kmemspace) /
 635      -                    (sizeof (struct tmpnode) + sizeof (struct tdirent));
 636      -        else
 637      -                sbp->f_ffree = 0;
 638      -
 639      -        sbp->f_files = tmpfs_maxkmem /
      633 +         * of tmpnodes we can allocate from the number of blocks available
      634 +         * to this mount.  This is fairly inaccurate since it doesn't take
      635 +         * into account the names stored in the directory entries.
      636 +         */
      637 +        sbp->f_ffree = sbp->f_bfree == 0 ? 0 : sbp->f_bfree /
      638 +            (sizeof (struct tmpnode) + sizeof (struct tdirent));
      639 +        sbp->f_files = sbp->f_blocks == 0 ? 0 : sbp->f_blocks /
 640  640              (sizeof (struct tmpnode) + sizeof (struct tdirent));
 641  641          sbp->f_favail = (fsfilcnt64_t)(sbp->f_ffree);
 642  642          (void) cmpldev(&d32, vfsp->vfs_dev);
 643  643          sbp->f_fsid = d32;
 644  644          (void) strcpy(sbp->f_basetype, vfssw[tmpfsfstype].vsw_name);
 645  645          (void) strncpy(sbp->f_fstr, tm->tm_mntpath, sizeof (sbp->f_fstr));
 646  646          /*
 647  647           * ensure null termination
 648  648           */
 649  649          sbp->f_fstr[sizeof (sbp->f_fstr) - 1] = '\0';
↓ open down ↓ 48 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX