Print this page
    
11927 Log, or optionally panic, on zero-length kmem allocations
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/os/fio.c
          +++ new/usr/src/uts/common/os/fio.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  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  /*
  23   23   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2015, Joyent Inc.
  25   25   */
  26   26  
  27   27  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28   28  /*      All Rights Reserved */
  29   29  
  30   30  #include <sys/types.h>
  31   31  #include <sys/sysmacros.h>
  32   32  #include <sys/param.h>
  33   33  #include <sys/systm.h>
  34   34  #include <sys/errno.h>
  35   35  #include <sys/signal.h>
  36   36  #include <sys/cred.h>
  37   37  #include <sys/user.h>
  38   38  #include <sys/conf.h>
  39   39  #include <sys/vfs.h>
  40   40  #include <sys/vnode.h>
  41   41  #include <sys/pathname.h>
  42   42  #include <sys/file.h>
  43   43  #include <sys/flock.h>
  44   44  #include <sys/proc.h>
  45   45  #include <sys/var.h>
  46   46  #include <sys/cpuvar.h>
  47   47  #include <sys/open.h>
  48   48  #include <sys/cmn_err.h>
  49   49  #include <sys/priocntl.h>
  50   50  #include <sys/procset.h>
  51   51  #include <sys/prsystm.h>
  52   52  #include <sys/debug.h>
  53   53  #include <sys/kmem.h>
  54   54  #include <sys/atomic.h>
  55   55  #include <sys/fcntl.h>
  56   56  #include <sys/poll.h>
  57   57  #include <sys/rctl.h>
  58   58  #include <sys/port_impl.h>
  59   59  #include <sys/dtrace.h>
  60   60  
  61   61  #include <c2/audit.h>
  62   62  #include <sys/nbmlock.h>
  63   63  
  64   64  #ifdef DEBUG
  65   65  
  66   66  static uint32_t afd_maxfd;      /* # of entries in maximum allocated array */
  67   67  static uint32_t afd_alloc;      /* count of kmem_alloc()s */
  68   68  static uint32_t afd_free;       /* count of kmem_free()s */
  69   69  static uint32_t afd_wait;       /* count of waits on non-zero ref count */
  70   70  #define MAXFD(x)        (afd_maxfd = ((afd_maxfd >= (x))? afd_maxfd : (x)))
  71   71  #define COUNT(x)        atomic_inc_32(&x)
  72   72  
  73   73  #else   /* DEBUG */
  74   74  
  75   75  #define MAXFD(x)
  76   76  #define COUNT(x)
  77   77  
  78   78  #endif  /* DEBUG */
  79   79  
  80   80  kmem_cache_t *file_cache;
  81   81  
  82   82  static void port_close_fd(portfd_t *);
  83   83  
  84   84  /*
  85   85   * File descriptor allocation.
  86   86   *
  87   87   * fd_find(fip, minfd) finds the first available descriptor >= minfd.
  88   88   * The most common case is open(2), in which minfd = 0, but we must also
  89   89   * support fcntl(fd, F_DUPFD, minfd).
  90   90   *
  91   91   * The algorithm is as follows: we keep all file descriptors in an infix
  92   92   * binary tree in which each node records the number of descriptors
  93   93   * allocated in its right subtree, including itself.  Starting at minfd,
  94   94   * we ascend the tree until we find a non-fully allocated right subtree.
  95   95   * We then descend that subtree in a binary search for the smallest fd.
  96   96   * Finally, we ascend the tree again to increment the allocation count
  97   97   * of every subtree containing the newly-allocated fd.  Freeing an fd
  98   98   * requires only the last step: we ascend the tree to decrement allocation
  99   99   * counts.  Each of these three steps (ascent to find non-full subtree,
 100  100   * descent to find lowest fd, ascent to update allocation counts) is
 101  101   * O(log n), thus the algorithm as a whole is O(log n).
 102  102   *
 103  103   * We don't implement the fd tree using the customary left/right/parent
 104  104   * pointers, but instead take advantage of the glorious mathematics of
 105  105   * full infix binary trees.  For reference, here's an illustration of the
 106  106   * logical structure of such a tree, rooted at 4 (binary 100), covering
 107  107   * the range 1-7 (binary 001-111).  Our canonical trees do not include
 108  108   * fd 0; we'll deal with that later.
 109  109   *
 110  110   *            100
 111  111   *           /   \
 112  112   *          /     \
 113  113   *        010     110
 114  114   *        / \     / \
 115  115   *      001 011 101 111
 116  116   *
 117  117   * We make the following observations, all of which are easily proven by
 118  118   * induction on the depth of the tree:
 119  119   *
 120  120   * (T1) The least-significant bit (LSB) of any node is equal to its level
 121  121   *      in the tree.  In our example, nodes 001, 011, 101 and 111 are at
 122  122   *      level 0; nodes 010 and 110 are at level 1; and node 100 is at level 2.
 123  123   *
 124  124   * (T2) The child size (CSIZE) of node N -- that is, the total number of
 125  125   *      right-branch descendants in a child of node N, including itself -- is
 126  126   *      given by clearing all but the least significant bit of N.  This
 127  127   *      follows immediately from (T1).  Applying this rule to our example, we
 128  128   *      see that CSIZE(100) = 100, CSIZE(x10) = 10, and CSIZE(xx1) = 1.
 129  129   *
 130  130   * (T3) The nearest left ancestor (LPARENT) of node N -- that is, the nearest
 131  131   *      ancestor containing node N in its right child -- is given by clearing
 132  132   *      the LSB of N.  For example, LPARENT(111) = 110 and LPARENT(110) = 100.
 133  133   *      Clearing the LSB of nodes 001, 010 or 100 yields zero, reflecting
 134  134   *      the fact that these are leftmost nodes.  Note that this algorithm
 135  135   *      automatically skips generations as necessary.  For example, the parent
 136  136   *      of node 101 is 110, which is a *right* ancestor (not what we want);
 137  137   *      but its grandparent is 100, which is a left ancestor. Clearing the LSB
 138  138   *      of 101 gets us to 100 directly, skipping right past the uninteresting
 139  139   *      generation (110).
 140  140   *
 141  141   *      Note that since LPARENT clears the LSB, whereas CSIZE clears all *but*
 142  142   *      the LSB, we can express LPARENT() nicely in terms of CSIZE():
 143  143   *
 144  144   *      LPARENT(N) = N - CSIZE(N)
 145  145   *
 146  146   * (T4) The nearest right ancestor (RPARENT) of node N is given by:
 147  147   *
 148  148   *      RPARENT(N) = N + CSIZE(N)
 149  149   *
 150  150   * (T5) For every interior node, the children differ from their parent by
 151  151   *      CSIZE(parent) / 2.  In our example, CSIZE(100) / 2 = 2 = 10 binary,
 152  152   *      and indeed, the children of 100 are 100 +/- 10 = 010 and 110.
 153  153   *
 154  154   * Next, we'll need a few two's-complement math tricks.  Suppose a number,
 155  155   * N, has the following form:
 156  156   *
 157  157   *              N = xxxx10...0
 158  158   *
 159  159   * That is, the binary representation of N consists of some string of bits,
 160  160   * then a 1, then all zeroes.  This amounts to nothing more than saying that
 161  161   * N has a least-significant bit, which is true for any N != 0.  If we look
 162  162   * at N and N - 1 together, we see that we can combine them in useful ways:
 163  163   *
 164  164   *                N = xxxx10...0
 165  165   *            N - 1 = xxxx01...1
 166  166   *      ------------------------
 167  167   *      N & (N - 1) = xxxx000000
 168  168   *      N | (N - 1) = xxxx111111
 169  169   *      N ^ (N - 1) =     111111
 170  170   *
 171  171   * In particular, this suggests several easy ways to clear all but the LSB,
 172  172   * which by (T2) is exactly what we need to determine CSIZE(N) = 10...0.
 173  173   * We'll opt for this formulation:
 174  174   *
 175  175   *      (C1) CSIZE(N) = (N - 1) ^ (N | (N - 1))
 176  176   *
 177  177   * Similarly, we have an easy way to determine LPARENT(N), which requires
 178  178   * that we clear the LSB of N:
 179  179   *
 180  180   *      (L1) LPARENT(N) = N & (N - 1)
 181  181   *
 182  182   * We note in the above relations that (N | (N - 1)) - N = CSIZE(N) - 1.
 183  183   * When combined with (T4), this yields an easy way to compute RPARENT(N):
 184  184   *
 185  185   *      (R1) RPARENT(N) = (N | (N - 1)) + 1
 186  186   *
 187  187   * Finally, to accommodate fd 0 we must adjust all of our results by +/-1 to
 188  188   * move the fd range from [1, 2^n) to [0, 2^n - 1).  This is straightforward,
 189  189   * so there's no need to belabor the algebra; the revised relations become:
 190  190   *
 191  191   *      (C1a) CSIZE(N) = N ^ (N | (N + 1))
 192  192   *
 193  193   *      (L1a) LPARENT(N) = (N & (N + 1)) - 1
 194  194   *
 195  195   *      (R1a) RPARENT(N) = N | (N + 1)
 196  196   *
 197  197   * This completes the mathematical framework.  We now have all the tools
 198  198   * we need to implement fd_find() and fd_reserve().
 199  199   *
 200  200   * fd_find(fip, minfd) finds the smallest available file descriptor >= minfd.
 201  201   * It does not actually allocate the descriptor; that's done by fd_reserve().
 202  202   * fd_find() proceeds in two steps:
 203  203   *
 204  204   * (1) Find the leftmost subtree that contains a descriptor >= minfd.
 205  205   *     We start at the right subtree rooted at minfd.  If this subtree is
 206  206   *     not full -- if fip->fi_list[minfd].uf_alloc != CSIZE(minfd) -- then
 207  207   *     step 1 is done.  Otherwise, we know that all fds in this subtree
 208  208   *     are taken, so we ascend to RPARENT(minfd) using (R1a).  We repeat
 209  209   *     this process until we either find a candidate subtree or exceed
 210  210   *     fip->fi_nfiles.  We use (C1a) to compute CSIZE().
 211  211   *
 212  212   * (2) Find the smallest fd in the subtree discovered by step 1.
 213  213   *     Starting at the root of this subtree, we descend to find the
 214  214   *     smallest available fd.  Since the left children have the smaller
 215  215   *     fds, we will descend rightward only when the left child is full.
 216  216   *
 217  217   *     We begin by comparing the number of allocated fds in the root
 218  218   *     to the number of allocated fds in its right child; if they differ
 219  219   *     by exactly CSIZE(child), we know the left subtree is full, so we
 220  220   *     descend right; that is, the right child becomes the search root.
 221  221   *     Otherwise we leave the root alone and start following the right
 222  222   *     child's left children.  As fortune would have it, this is very
 223  223   *     simple computationally: by (T5), the right child of fd is just
 224  224   *     fd + size, where size = CSIZE(fd) / 2.  Applying (T5) again,
 225  225   *     we find that the right child's left child is fd + size - (size / 2) =
 226  226   *     fd + (size / 2); *its* left child is fd + (size / 2) - (size / 4) =
 227  227   *     fd + (size / 4), and so on.  In general, fd's right child's
 228  228   *     leftmost nth descendant is fd + (size >> n).  Thus, to follow
 229  229   *     the right child's left descendants, we just halve the size in
 230  230   *     each iteration of the search.
 231  231   *
 232  232   *     When we descend leftward, we must keep track of the number of fds
 233  233   *     that were allocated in all the right subtrees we rejected, so we
 234  234   *     know how many of the root fd's allocations are in the remaining
 235  235   *     (as yet unexplored) leftmost part of its right subtree.  When we
 236  236   *     encounter a fully-allocated left child -- that is, when we find
 237  237   *     that fip->fi_list[fd].uf_alloc == ralloc + size -- we descend right
 238  238   *     (as described earlier), resetting ralloc to zero.
 239  239   *
 240  240   * fd_reserve(fip, fd, incr) either allocates or frees fd, depending
 241  241   * on whether incr is 1 or -1.  Starting at fd, fd_reserve() ascends
 242  242   * the leftmost ancestors (see (T3)) and updates the allocation counts.
 243  243   * At each step we use (L1a) to compute LPARENT(), the next left ancestor.
 244  244   *
 245  245   * flist_minsize() finds the minimal tree that still covers all
 246  246   * used fds; as long as the allocation count of a root node is zero, we
 247  247   * don't need that node or its right subtree.
 248  248   *
 249  249   * flist_nalloc() counts the number of allocated fds in the tree, by starting
 250  250   * at the top of the tree and summing the right-subtree allocation counts as
 251  251   * it descends leftwards.
 252  252   *
 253  253   * Note: we assume that flist_grow() will keep fip->fi_nfiles of the form
 254  254   * 2^n - 1.  This ensures that the fd trees are always full, which saves
 255  255   * quite a bit of boundary checking.
 256  256   */
 257  257  static int
 258  258  fd_find(uf_info_t *fip, int minfd)
 259  259  {
 260  260          int size, ralloc, fd;
 261  261  
 262  262          ASSERT(MUTEX_HELD(&fip->fi_lock));
 263  263          ASSERT((fip->fi_nfiles & (fip->fi_nfiles + 1)) == 0);
 264  264  
 265  265          for (fd = minfd; (uint_t)fd < fip->fi_nfiles; fd |= fd + 1) {
 266  266                  size = fd ^ (fd | (fd + 1));
 267  267                  if (fip->fi_list[fd].uf_alloc == size)
 268  268                          continue;
 269  269                  for (ralloc = 0, size >>= 1; size != 0; size >>= 1) {
 270  270                          ralloc += fip->fi_list[fd + size].uf_alloc;
 271  271                          if (fip->fi_list[fd].uf_alloc == ralloc + size) {
 272  272                                  fd += size;
 273  273                                  ralloc = 0;
 274  274                          }
 275  275                  }
 276  276                  return (fd);
 277  277          }
 278  278          return (-1);
 279  279  }
 280  280  
 281  281  static void
 282  282  fd_reserve(uf_info_t *fip, int fd, int incr)
 283  283  {
 284  284          int pfd;
 285  285          uf_entry_t *ufp = &fip->fi_list[fd];
 286  286  
 287  287          ASSERT((uint_t)fd < fip->fi_nfiles);
 288  288          ASSERT((ufp->uf_busy == 0 && incr == 1) ||
 289  289              (ufp->uf_busy == 1 && incr == -1));
 290  290          ASSERT(MUTEX_HELD(&ufp->uf_lock));
 291  291          ASSERT(MUTEX_HELD(&fip->fi_lock));
 292  292  
 293  293          for (pfd = fd; pfd >= 0; pfd = (pfd & (pfd + 1)) - 1)
 294  294                  fip->fi_list[pfd].uf_alloc += incr;
 295  295  
 296  296          ufp->uf_busy += incr;
 297  297  }
 298  298  
 299  299  static int
 300  300  flist_minsize(uf_info_t *fip)
 301  301  {
 302  302          int fd;
 303  303  
 304  304          /*
 305  305           * We'd like to ASSERT(MUTEX_HELD(&fip->fi_lock)), but we're called
 306  306           * by flist_fork(), which relies on other mechanisms for mutual
 307  307           * exclusion.
 308  308           */
 309  309          ASSERT((fip->fi_nfiles & (fip->fi_nfiles + 1)) == 0);
 310  310  
 311  311          for (fd = fip->fi_nfiles; fd != 0; fd >>= 1)
 312  312                  if (fip->fi_list[fd >> 1].uf_alloc != 0)
 313  313                          break;
 314  314  
 315  315          return (fd);
 316  316  }
 317  317  
 318  318  static int
 319  319  flist_nalloc(uf_info_t *fip)
 320  320  {
 321  321          int fd;
 322  322          int nalloc = 0;
 323  323  
 324  324          ASSERT(MUTEX_HELD(&fip->fi_lock));
 325  325          ASSERT((fip->fi_nfiles & (fip->fi_nfiles + 1)) == 0);
 326  326  
 327  327          for (fd = fip->fi_nfiles; fd != 0; fd >>= 1)
 328  328                  nalloc += fip->fi_list[fd >> 1].uf_alloc;
 329  329  
 330  330          return (nalloc);
 331  331  }
 332  332  
 333  333  /*
 334  334   * Increase size of the fi_list array to accommodate at least maxfd.
 335  335   * We keep the size of the form 2^n - 1 for benefit of fd_find().
 336  336   */
 337  337  static void
 338  338  flist_grow(int maxfd)
 339  339  {
 340  340          uf_info_t *fip = P_FINFO(curproc);
 341  341          int newcnt, oldcnt;
 342  342          uf_entry_t *src, *dst, *newlist, *oldlist, *newend, *oldend;
 343  343          uf_rlist_t *urp;
 344  344  
 345  345          for (newcnt = 1; newcnt <= maxfd; newcnt = (newcnt << 1) | 1)
 346  346                  continue;
 347  347  
 348  348          newlist = kmem_zalloc(newcnt * sizeof (uf_entry_t), KM_SLEEP);
 349  349  
 350  350          mutex_enter(&fip->fi_lock);
 351  351          oldcnt = fip->fi_nfiles;
 352  352          if (newcnt <= oldcnt) {
 353  353                  mutex_exit(&fip->fi_lock);
 354  354                  kmem_free(newlist, newcnt * sizeof (uf_entry_t));
 355  355                  return;
 356  356          }
 357  357          ASSERT((newcnt & (newcnt + 1)) == 0);
 358  358          oldlist = fip->fi_list;
 359  359          oldend = oldlist + oldcnt;
 360  360          newend = newlist + oldcnt;      /* no need to lock beyond old end */
 361  361  
 362  362          /*
 363  363           * fi_list and fi_nfiles cannot change while any uf_lock is held,
 364  364           * so we must grab all the old locks *and* the new locks up to oldcnt.
 365  365           * (Locks beyond the end of oldcnt aren't visible until we store
 366  366           * the new fi_nfiles, which is the last thing we do before dropping
 367  367           * all the locks, so there's no need to acquire these locks).
 368  368           * Holding the new locks is necessary because when fi_list changes
 369  369           * to point to the new list, fi_nfiles won't have been stored yet.
 370  370           * If we *didn't* hold the new locks, someone doing a UF_ENTER()
 371  371           * could see the new fi_list, grab the new uf_lock, and then see
 372  372           * fi_nfiles change while the lock is held -- in violation of
 373  373           * UF_ENTER() semantics.
 374  374           */
 375  375          for (src = oldlist; src < oldend; src++)
 376  376                  mutex_enter(&src->uf_lock);
 377  377  
 378  378          for (dst = newlist; dst < newend; dst++)
 379  379                  mutex_enter(&dst->uf_lock);
 380  380  
 381  381          for (src = oldlist, dst = newlist; src < oldend; src++, dst++) {
 382  382                  dst->uf_file = src->uf_file;
 383  383                  dst->uf_fpollinfo = src->uf_fpollinfo;
 384  384                  dst->uf_refcnt = src->uf_refcnt;
 385  385                  dst->uf_alloc = src->uf_alloc;
 386  386                  dst->uf_flag = src->uf_flag;
 387  387                  dst->uf_busy = src->uf_busy;
 388  388                  dst->uf_portfd = src->uf_portfd;
 389  389          }
 390  390  
 391  391          /*
 392  392           * As soon as we store the new flist, future locking operations
 393  393           * will use it.  Therefore, we must ensure that all the state
 394  394           * we've just established reaches global visibility before the
 395  395           * new flist does.
 396  396           */
 397  397          membar_producer();
 398  398          fip->fi_list = newlist;
 399  399  
 400  400          /*
 401  401           * Routines like getf() make an optimistic check on the validity
 402  402           * of the supplied file descriptor: if it's less than the current
 403  403           * value of fi_nfiles -- examined without any locks -- then it's
 404  404           * safe to attempt a UF_ENTER() on that fd (which is a valid
 405  405           * assumption because fi_nfiles only increases).  Therefore, it
 406  406           * is critical that the new value of fi_nfiles not reach global
 407  407           * visibility until after the new fi_list: if it happened the
 408  408           * other way around, getf() could see the new fi_nfiles and attempt
 409  409           * a UF_ENTER() on the old fi_list, which would write beyond its
 410  410           * end if the fd exceeded the old fi_nfiles.
 411  411           */
 412  412          membar_producer();
 413  413          fip->fi_nfiles = newcnt;
 414  414  
 415  415          /*
 416  416           * The new state is consistent now, so we can drop all the locks.
 417  417           */
 418  418          for (dst = newlist; dst < newend; dst++)
 419  419                  mutex_exit(&dst->uf_lock);
 420  420  
 421  421          for (src = oldlist; src < oldend; src++) {
 422  422                  /*
 423  423                   * If any threads are blocked on the old cvs, wake them.
 424  424                   * This will force them to wake up, discover that fi_list
 425  425                   * has changed, and go back to sleep on the new cvs.
 426  426                   */
 427  427                  cv_broadcast(&src->uf_wanted_cv);
 428  428                  cv_broadcast(&src->uf_closing_cv);
 429  429                  mutex_exit(&src->uf_lock);
 430  430          }
 431  431  
 432  432          mutex_exit(&fip->fi_lock);
 433  433  
 434  434          /*
 435  435           * Retire the old flist.  We can't actually kmem_free() it now
 436  436           * because someone may still have a pointer to it.  Instead,
 437  437           * we link it onto a list of retired flists.  The new flist
 438  438           * is at least double the size of the previous flist, so the
 439  439           * total size of all retired flists will be less than the size
 440  440           * of the current one (to prove, consider the sum of a geometric
 441  441           * series in powers of 2).  exit() frees the retired flists.
 442  442           */
 443  443          urp = kmem_zalloc(sizeof (uf_rlist_t), KM_SLEEP);
 444  444          urp->ur_list = oldlist;
 445  445          urp->ur_nfiles = oldcnt;
 446  446  
 447  447          mutex_enter(&fip->fi_lock);
 448  448          urp->ur_next = fip->fi_rlist;
 449  449          fip->fi_rlist = urp;
 450  450          mutex_exit(&fip->fi_lock);
 451  451  }
 452  452  
 453  453  /*
 454  454   * Utility functions for keeping track of the active file descriptors.
 455  455   */
 456  456  void
 457  457  clear_stale_fd()                /* called from post_syscall() */
 458  458  {
 459  459          afd_t *afd = &curthread->t_activefd;
 460  460          int i;
 461  461  
 462  462          /* uninitialized is ok here, a_nfd is then zero */
 463  463          for (i = 0; i < afd->a_nfd; i++) {
 464  464                  /* assert that this should not be necessary */
 465  465                  ASSERT(afd->a_fd[i] == -1);
 466  466                  afd->a_fd[i] = -1;
 467  467          }
 468  468          afd->a_stale = 0;
 469  469  }
 470  470  
 471  471  void
 472  472  free_afd(afd_t *afd)            /* called below and from thread_free() */
 473  473  {
 474  474          int i;
 475  475  
 476  476          /* free the buffer if it was kmem_alloc()ed */
 477  477          if (afd->a_nfd > sizeof (afd->a_buf) / sizeof (afd->a_buf[0])) {
 478  478                  COUNT(afd_free);
 479  479                  kmem_free(afd->a_fd, afd->a_nfd * sizeof (afd->a_fd[0]));
 480  480          }
 481  481  
 482  482          /* (re)initialize the structure */
 483  483          afd->a_fd = &afd->a_buf[0];
 484  484          afd->a_nfd = sizeof (afd->a_buf) / sizeof (afd->a_buf[0]);
 485  485          afd->a_stale = 0;
 486  486          for (i = 0; i < afd->a_nfd; i++)
 487  487                  afd->a_fd[i] = -1;
 488  488  }
 489  489  
 490  490  static void
 491  491  set_active_fd(int fd)
 492  492  {
 493  493          afd_t *afd = &curthread->t_activefd;
 494  494          int i;
 495  495          int *old_fd;
 496  496          int old_nfd;
 497  497          int *new_fd;
 498  498          int new_nfd;
 499  499  
 500  500          if (afd->a_nfd == 0) {  /* first time initialization */
 501  501                  ASSERT(fd == -1);
 502  502                  mutex_enter(&afd->a_fdlock);
 503  503                  free_afd(afd);
 504  504                  mutex_exit(&afd->a_fdlock);
 505  505          }
 506  506  
 507  507          /* insert fd into vacant slot, if any */
 508  508          for (i = 0; i < afd->a_nfd; i++) {
 509  509                  if (afd->a_fd[i] == -1) {
 510  510                          afd->a_fd[i] = fd;
 511  511                          return;
 512  512                  }
 513  513          }
 514  514  
 515  515          /*
 516  516           * Reallocate the a_fd[] array to add one more slot.
 517  517           */
 518  518          ASSERT(fd == -1);
 519  519          old_nfd = afd->a_nfd;
 520  520          old_fd = afd->a_fd;
 521  521          new_nfd = old_nfd + 1;
 522  522          new_fd = kmem_alloc(new_nfd * sizeof (afd->a_fd[0]), KM_SLEEP);
 523  523          MAXFD(new_nfd);
 524  524          COUNT(afd_alloc);
 525  525  
 526  526          mutex_enter(&afd->a_fdlock);
 527  527          afd->a_fd = new_fd;
 528  528          afd->a_nfd = new_nfd;
 529  529          for (i = 0; i < old_nfd; i++)
 530  530                  afd->a_fd[i] = old_fd[i];
 531  531          afd->a_fd[i] = fd;
 532  532          mutex_exit(&afd->a_fdlock);
 533  533  
 534  534          if (old_nfd > sizeof (afd->a_buf) / sizeof (afd->a_buf[0])) {
 535  535                  COUNT(afd_free);
 536  536                  kmem_free(old_fd, old_nfd * sizeof (afd->a_fd[0]));
 537  537          }
 538  538  }
 539  539  
 540  540  void
 541  541  clear_active_fd(int fd)         /* called below and from aio.c */
 542  542  {
 543  543          afd_t *afd = &curthread->t_activefd;
 544  544          int i;
 545  545  
 546  546          for (i = 0; i < afd->a_nfd; i++) {
 547  547                  if (afd->a_fd[i] == fd) {
 548  548                          afd->a_fd[i] = -1;
 549  549                          break;
 550  550                  }
 551  551          }
 552  552          ASSERT(i < afd->a_nfd);         /* not found is not ok */
 553  553  }
 554  554  
 555  555  /*
 556  556   * Does this thread have this fd active?
 557  557   */
 558  558  static int
 559  559  is_active_fd(kthread_t *t, int fd)
 560  560  {
 561  561          afd_t *afd = &t->t_activefd;
 562  562          int i;
 563  563  
 564  564          ASSERT(t != curthread);
 565  565          mutex_enter(&afd->a_fdlock);
 566  566          /* uninitialized is ok here, a_nfd is then zero */
 567  567          for (i = 0; i < afd->a_nfd; i++) {
 568  568                  if (afd->a_fd[i] == fd) {
 569  569                          mutex_exit(&afd->a_fdlock);
 570  570                          return (1);
 571  571                  }
 572  572          }
 573  573          mutex_exit(&afd->a_fdlock);
 574  574          return (0);
 575  575  }
 576  576  
 577  577  /*
 578  578   * Convert a user supplied file descriptor into a pointer to a file
 579  579   * structure.  Only task is to check range of the descriptor (soft
 580  580   * resource limit was enforced at open time and shouldn't be checked
 581  581   * here).
 582  582   */
 583  583  file_t *
 584  584  getf(int fd)
 585  585  {
 586  586          uf_info_t *fip = P_FINFO(curproc);
 587  587          uf_entry_t *ufp;
 588  588          file_t *fp;
 589  589  
 590  590          if ((uint_t)fd >= fip->fi_nfiles)
 591  591                  return (NULL);
 592  592  
 593  593          /*
 594  594           * Reserve a slot in the active fd array now so we can call
 595  595           * set_active_fd(fd) for real below, while still inside UF_ENTER().
 596  596           */
 597  597          set_active_fd(-1);
 598  598  
 599  599          UF_ENTER(ufp, fip, fd);
 600  600  
 601  601          if ((fp = ufp->uf_file) == NULL) {
 602  602                  UF_EXIT(ufp);
 603  603  
 604  604                  if (fd == fip->fi_badfd && fip->fi_action > 0)
 605  605                          tsignal(curthread, fip->fi_action);
 606  606  
 607  607                  return (NULL);
 608  608          }
 609  609          ufp->uf_refcnt++;
 610  610  
 611  611          set_active_fd(fd);      /* record the active file descriptor */
 612  612  
 613  613          UF_EXIT(ufp);
 614  614  
 615  615          return (fp);
 616  616  }
 617  617  
 618  618  /*
 619  619   * Close whatever file currently occupies the file descriptor slot
 620  620   * and install the new file, usually NULL, in the file descriptor slot.
 621  621   * The close must complete before we release the file descriptor slot.
 622  622   * If newfp != NULL we only return an error if we can't allocate the
 623  623   * slot so the caller knows that it needs to free the filep;
 624  624   * in the other cases we return the error number from closef().
 625  625   */
 626  626  int
 627  627  closeandsetf(int fd, file_t *newfp)
 628  628  {
 629  629          proc_t *p = curproc;
 630  630          uf_info_t *fip = P_FINFO(p);
 631  631          uf_entry_t *ufp;
 632  632          file_t *fp;
 633  633          fpollinfo_t *fpip;
 634  634          portfd_t *pfd;
 635  635          int error;
 636  636  
 637  637          if ((uint_t)fd >= fip->fi_nfiles) {
 638  638                  if (newfp == NULL)
 639  639                          return (EBADF);
 640  640                  flist_grow(fd);
 641  641          }
 642  642  
 643  643          if (newfp != NULL) {
 644  644                  /*
 645  645                   * If ufp is reserved but has no file pointer, it's in the
 646  646                   * transition between ufalloc() and setf().  We must wait
 647  647                   * for this transition to complete before assigning the
 648  648                   * new non-NULL file pointer.
 649  649                   */
 650  650                  mutex_enter(&fip->fi_lock);
 651  651                  if (fd == fip->fi_badfd) {
 652  652                          mutex_exit(&fip->fi_lock);
 653  653                          if (fip->fi_action > 0)
 654  654                                  tsignal(curthread, fip->fi_action);
 655  655                          return (EBADF);
 656  656                  }
 657  657                  UF_ENTER(ufp, fip, fd);
 658  658                  while (ufp->uf_busy && ufp->uf_file == NULL) {
 659  659                          mutex_exit(&fip->fi_lock);
 660  660                          cv_wait_stop(&ufp->uf_wanted_cv, &ufp->uf_lock, 250);
 661  661                          UF_EXIT(ufp);
 662  662                          mutex_enter(&fip->fi_lock);
 663  663                          UF_ENTER(ufp, fip, fd);
 664  664                  }
 665  665                  if ((fp = ufp->uf_file) == NULL) {
 666  666                          ASSERT(ufp->uf_fpollinfo == NULL);
 667  667                          ASSERT(ufp->uf_flag == 0);
 668  668                          fd_reserve(fip, fd, 1);
 669  669                          ufp->uf_file = newfp;
 670  670                          UF_EXIT(ufp);
 671  671                          mutex_exit(&fip->fi_lock);
 672  672                          return (0);
 673  673                  }
 674  674                  mutex_exit(&fip->fi_lock);
 675  675          } else {
 676  676                  UF_ENTER(ufp, fip, fd);
 677  677                  if ((fp = ufp->uf_file) == NULL) {
 678  678                          UF_EXIT(ufp);
 679  679                          return (EBADF);
 680  680                  }
 681  681          }
 682  682  
 683  683          ASSERT(ufp->uf_busy);
 684  684          ufp->uf_file = NULL;
 685  685          ufp->uf_flag = 0;
 686  686  
 687  687          /*
 688  688           * If the file descriptor reference count is non-zero, then
 689  689           * some other lwp in the process is performing system call
 690  690           * activity on the file.  To avoid blocking here for a long
 691  691           * time (the other lwp might be in a long term sleep in its
 692  692           * system call), we scan all other lwps in the process to
 693  693           * find the ones with this fd as one of their active fds,
 694  694           * set their a_stale flag, and set them running if they
 695  695           * are in an interruptible sleep so they will emerge from
 696  696           * their system calls immediately.  post_syscall() will
 697  697           * test the a_stale flag and set errno to EBADF.
 698  698           */
 699  699          ASSERT(ufp->uf_refcnt == 0 || p->p_lwpcnt > 1);
 700  700          if (ufp->uf_refcnt > 0) {
 701  701                  kthread_t *t;
 702  702  
 703  703                  /*
 704  704                   * We call sprlock_proc(p) to ensure that the thread
 705  705                   * list will not change while we are scanning it.
 706  706                   * To do this, we must drop ufp->uf_lock and then
 707  707                   * reacquire it (so we are not holding both p->p_lock
 708  708                   * and ufp->uf_lock at the same time).  ufp->uf_lock
 709  709                   * must be held for is_active_fd() to be correct
 710  710                   * (set_active_fd() is called while holding ufp->uf_lock).
 711  711                   *
 712  712                   * This is a convoluted dance, but it is better than
 713  713                   * the old brute-force method of stopping every thread
 714  714                   * in the process by calling holdlwps(SHOLDFORK1).
 715  715                   */
 716  716  
 717  717                  UF_EXIT(ufp);
 718  718                  COUNT(afd_wait);
 719  719  
 720  720                  mutex_enter(&p->p_lock);
 721  721                  sprlock_proc(p);
 722  722                  mutex_exit(&p->p_lock);
 723  723  
 724  724                  UF_ENTER(ufp, fip, fd);
 725  725                  ASSERT(ufp->uf_file == NULL);
 726  726  
 727  727                  if (ufp->uf_refcnt > 0) {
 728  728                          for (t = curthread->t_forw;
 729  729                              t != curthread;
 730  730                              t = t->t_forw) {
 731  731                                  if (is_active_fd(t, fd)) {
 732  732                                          thread_lock(t);
 733  733                                          t->t_activefd.a_stale = 1;
 734  734                                          t->t_post_sys = 1;
 735  735                                          if (ISWAKEABLE(t))
 736  736                                                  setrun_locked(t);
 737  737                                          thread_unlock(t);
 738  738                                  }
 739  739                          }
 740  740                  }
 741  741  
 742  742                  UF_EXIT(ufp);
 743  743  
 744  744                  mutex_enter(&p->p_lock);
 745  745                  sprunlock(p);
 746  746  
 747  747                  UF_ENTER(ufp, fip, fd);
 748  748                  ASSERT(ufp->uf_file == NULL);
 749  749          }
 750  750  
 751  751          /*
 752  752           * Wait for other lwps to stop using this file descriptor.
 753  753           */
 754  754          while (ufp->uf_refcnt > 0) {
 755  755                  cv_wait_stop(&ufp->uf_closing_cv, &ufp->uf_lock, 250);
 756  756                  /*
 757  757                   * cv_wait_stop() drops ufp->uf_lock, so the file list
 758  758                   * can change.  Drop the lock on our (possibly) stale
 759  759                   * ufp and let UF_ENTER() find and lock the current ufp.
 760  760                   */
 761  761                  UF_EXIT(ufp);
 762  762                  UF_ENTER(ufp, fip, fd);
 763  763          }
 764  764  
 765  765  #ifdef DEBUG
 766  766          /*
 767  767           * catch a watchfd on device's pollhead list but not on fpollinfo list
 768  768           */
 769  769          if (ufp->uf_fpollinfo != NULL)
 770  770                  checkwfdlist(fp->f_vnode, ufp->uf_fpollinfo);
 771  771  #endif  /* DEBUG */
 772  772  
 773  773          /*
 774  774           * We may need to cleanup some cached poll states in t_pollstate
 775  775           * before the fd can be reused. It is important that we don't
 776  776           * access a stale thread structure. We will do the cleanup in two
 777  777           * phases to avoid deadlock and holding uf_lock for too long.
 778  778           * In phase 1, hold the uf_lock and call pollblockexit() to set
 779  779           * state in t_pollstate struct so that a thread does not exit on
 780  780           * us. In phase 2, we drop the uf_lock and call pollcacheclean().
 781  781           */
 782  782          pfd = ufp->uf_portfd;
 783  783          ufp->uf_portfd = NULL;
 784  784          fpip = ufp->uf_fpollinfo;
 785  785          ufp->uf_fpollinfo = NULL;
 786  786          if (fpip != NULL)
 787  787                  pollblockexit(fpip);
 788  788          UF_EXIT(ufp);
 789  789          if (fpip != NULL)
 790  790                  pollcacheclean(fpip, fd);
 791  791          if (pfd)
 792  792                  port_close_fd(pfd);
 793  793  
 794  794          /*
 795  795           * Keep the file descriptor entry reserved across the closef().
 796  796           */
 797  797          error = closef(fp);
 798  798  
 799  799          setf(fd, newfp);
 800  800  
 801  801          /* Only return closef() error when closing is all we do */
 802  802          return (newfp == NULL ? error : 0);
 803  803  }
 804  804  
 805  805  /*
 806  806   * Decrement uf_refcnt; wakeup anyone waiting to close the file.
 807  807   */
 808  808  void
 809  809  releasef(int fd)
 810  810  {
 811  811          uf_info_t *fip = P_FINFO(curproc);
 812  812          uf_entry_t *ufp;
 813  813  
 814  814          UF_ENTER(ufp, fip, fd);
 815  815          ASSERT(ufp->uf_refcnt > 0);
 816  816          clear_active_fd(fd);    /* clear the active file descriptor */
 817  817          if (--ufp->uf_refcnt == 0)
 818  818                  cv_broadcast(&ufp->uf_closing_cv);
 819  819          UF_EXIT(ufp);
 820  820  }
 821  821  
 822  822  /*
 823  823   * Identical to releasef() but can be called from another process.
 824  824   */
 825  825  void
 826  826  areleasef(int fd, uf_info_t *fip)
 827  827  {
 828  828          uf_entry_t *ufp;
 829  829  
 830  830          UF_ENTER(ufp, fip, fd);
 831  831          ASSERT(ufp->uf_refcnt > 0);
 832  832          if (--ufp->uf_refcnt == 0)
 833  833                  cv_broadcast(&ufp->uf_closing_cv);
 834  834          UF_EXIT(ufp);
 835  835  }
 836  836  
 837  837  /*
 838  838   * Duplicate all file descriptors across a fork.
 839  839   */
 840  840  void
 841  841  flist_fork(uf_info_t *pfip, uf_info_t *cfip)
 842  842  {
 843  843          int fd, nfiles;
 844  844          uf_entry_t *pufp, *cufp;
  
    | 
      ↓ open down ↓ | 
    844 lines elided | 
    
      ↑ open up ↑ | 
  
 845  845  
 846  846          mutex_init(&cfip->fi_lock, NULL, MUTEX_DEFAULT, NULL);
 847  847          cfip->fi_rlist = NULL;
 848  848  
 849  849          /*
 850  850           * We don't need to hold fi_lock because all other lwp's in the
 851  851           * parent have been held.
 852  852           */
 853  853          cfip->fi_nfiles = nfiles = flist_minsize(pfip);
 854  854  
 855      -        cfip->fi_list = kmem_zalloc(nfiles * sizeof (uf_entry_t), KM_SLEEP);
      855 +        cfip->fi_list = nfiles == 0 ? NULL :
      856 +            kmem_zalloc(nfiles * sizeof (uf_entry_t), KM_SLEEP);
 856  857  
 857  858          for (fd = 0, pufp = pfip->fi_list, cufp = cfip->fi_list; fd < nfiles;
 858  859              fd++, pufp++, cufp++) {
 859  860                  cufp->uf_file = pufp->uf_file;
 860  861                  cufp->uf_alloc = pufp->uf_alloc;
 861  862                  cufp->uf_flag = pufp->uf_flag;
 862  863                  cufp->uf_busy = pufp->uf_busy;
 863  864                  if (pufp->uf_file == NULL) {
 864  865                          ASSERT(pufp->uf_flag == 0);
 865  866                          if (pufp->uf_busy) {
 866  867                                  /*
 867  868                                   * Grab locks to appease ASSERTs in fd_reserve
 868  869                                   */
 869  870                                  mutex_enter(&cfip->fi_lock);
 870  871                                  mutex_enter(&cufp->uf_lock);
 871  872                                  fd_reserve(cfip, fd, -1);
 872  873                                  mutex_exit(&cufp->uf_lock);
 873  874                                  mutex_exit(&cfip->fi_lock);
 874  875                          }
 875  876                  }
 876  877          }
 877  878  }
 878  879  
 879  880  /*
 880  881   * Close all open file descriptors for the current process.
 881  882   * This is only called from exit(), which is single-threaded,
 882  883   * so we don't need any locking.
 883  884   */
 884  885  void
 885  886  closeall(uf_info_t *fip)
 886  887  {
 887  888          int fd;
 888  889          file_t *fp;
 889  890          uf_entry_t *ufp;
 890  891  
 891  892          ufp = fip->fi_list;
 892  893          for (fd = 0; fd < fip->fi_nfiles; fd++, ufp++) {
 893  894                  if ((fp = ufp->uf_file) != NULL) {
 894  895                          ufp->uf_file = NULL;
 895  896                          if (ufp->uf_portfd != NULL) {
 896  897                                  portfd_t *pfd;
 897  898                                  /* remove event port association */
 898  899                                  pfd = ufp->uf_portfd;
 899  900                                  ufp->uf_portfd = NULL;
 900  901                                  port_close_fd(pfd);
 901  902                          }
 902  903                          ASSERT(ufp->uf_fpollinfo == NULL);
 903  904                          (void) closef(fp);
 904  905                  }
 905  906          }
 906  907  
 907  908          kmem_free(fip->fi_list, fip->fi_nfiles * sizeof (uf_entry_t));
 908  909          fip->fi_list = NULL;
 909  910          fip->fi_nfiles = 0;
 910  911          while (fip->fi_rlist != NULL) {
 911  912                  uf_rlist_t *urp = fip->fi_rlist;
 912  913                  fip->fi_rlist = urp->ur_next;
 913  914                  kmem_free(urp->ur_list, urp->ur_nfiles * sizeof (uf_entry_t));
 914  915                  kmem_free(urp, sizeof (uf_rlist_t));
 915  916          }
 916  917  }
 917  918  
 918  919  /*
 919  920   * Internal form of close.  Decrement reference count on file
 920  921   * structure.  Decrement reference count on the vnode following
 921  922   * removal of the referencing file structure.
 922  923   */
 923  924  int
 924  925  closef(file_t *fp)
 925  926  {
 926  927          vnode_t *vp;
 927  928          int error;
 928  929          int count;
 929  930          int flag;
 930  931          offset_t offset;
 931  932  
 932  933          /*
 933  934           * audit close of file (may be exit)
 934  935           */
 935  936          if (AU_AUDITING())
 936  937                  audit_closef(fp);
 937  938          ASSERT(MUTEX_NOT_HELD(&P_FINFO(curproc)->fi_lock));
 938  939  
 939  940          mutex_enter(&fp->f_tlock);
 940  941  
 941  942          ASSERT(fp->f_count > 0);
 942  943  
 943  944          count = fp->f_count--;
 944  945          flag = fp->f_flag;
 945  946          offset = fp->f_offset;
 946  947  
 947  948          vp = fp->f_vnode;
 948  949  
 949  950          error = VOP_CLOSE(vp, flag, count, offset, fp->f_cred, NULL);
 950  951  
 951  952          if (count > 1) {
 952  953                  mutex_exit(&fp->f_tlock);
 953  954                  return (error);
 954  955          }
 955  956          ASSERT(fp->f_count == 0);
 956  957          /* Last reference, remove any OFD style lock for the file_t */
 957  958          ofdcleanlock(fp);
 958  959          mutex_exit(&fp->f_tlock);
 959  960  
 960  961          /*
 961  962           * If DTrace has getf() subroutines active, it will set dtrace_closef
 962  963           * to point to code that implements a barrier with respect to probe
 963  964           * context.  This must be called before the file_t is freed (and the
 964  965           * vnode that it refers to is released) -- but it must be after the
 965  966           * file_t has been removed from the uf_entry_t.  That is, there must
 966  967           * be no way for a racing getf() in probe context to yield the fp that
 967  968           * we're operating upon.
 968  969           */
 969  970          if (dtrace_closef != NULL)
 970  971                  (*dtrace_closef)();
 971  972  
 972  973          VN_RELE(vp);
 973  974          /*
 974  975           * deallocate resources to audit_data
 975  976           */
 976  977          if (audit_active)
 977  978                  audit_unfalloc(fp);
 978  979          crfree(fp->f_cred);
 979  980          kmem_cache_free(file_cache, fp);
 980  981          return (error);
 981  982  }
 982  983  
 983  984  /*
 984  985   * This is a combination of ufalloc() and setf().
 985  986   */
 986  987  int
 987  988  ufalloc_file(int start, file_t *fp)
 988  989  {
 989  990          proc_t *p = curproc;
 990  991          uf_info_t *fip = P_FINFO(p);
 991  992          int filelimit;
 992  993          uf_entry_t *ufp;
 993  994          int nfiles;
 994  995          int fd;
 995  996  
 996  997          /*
 997  998           * Assertion is to convince the correctness of the following
 998  999           * assignment for filelimit after casting to int.
 999 1000           */
1000 1001          ASSERT(p->p_fno_ctl <= INT_MAX);
1001 1002          filelimit = (int)p->p_fno_ctl;
1002 1003  
1003 1004          for (;;) {
1004 1005                  mutex_enter(&fip->fi_lock);
1005 1006                  fd = fd_find(fip, start);
1006 1007                  if (fd >= 0 && fd == fip->fi_badfd) {
1007 1008                          start = fd + 1;
1008 1009                          mutex_exit(&fip->fi_lock);
1009 1010                          continue;
1010 1011                  }
1011 1012                  if ((uint_t)fd < filelimit)
1012 1013                          break;
1013 1014                  if (fd >= filelimit) {
1014 1015                          mutex_exit(&fip->fi_lock);
1015 1016                          mutex_enter(&p->p_lock);
1016 1017                          (void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE],
1017 1018                              p->p_rctls, p, RCA_SAFE);
1018 1019                          mutex_exit(&p->p_lock);
1019 1020                          return (-1);
1020 1021                  }
1021 1022                  /* fd_find() returned -1 */
1022 1023                  nfiles = fip->fi_nfiles;
1023 1024                  mutex_exit(&fip->fi_lock);
1024 1025                  flist_grow(MAX(start, nfiles));
1025 1026          }
1026 1027  
1027 1028          UF_ENTER(ufp, fip, fd);
1028 1029          fd_reserve(fip, fd, 1);
1029 1030          ASSERT(ufp->uf_file == NULL);
1030 1031          ufp->uf_file = fp;
1031 1032          UF_EXIT(ufp);
1032 1033          mutex_exit(&fip->fi_lock);
1033 1034          return (fd);
1034 1035  }
1035 1036  
1036 1037  /*
1037 1038   * Allocate a user file descriptor greater than or equal to "start".
1038 1039   */
1039 1040  int
1040 1041  ufalloc(int start)
1041 1042  {
1042 1043          return (ufalloc_file(start, NULL));
1043 1044  }
1044 1045  
1045 1046  /*
1046 1047   * Check that a future allocation of count fds on proc p has a good
1047 1048   * chance of succeeding.  If not, do rctl processing as if we'd failed
1048 1049   * the allocation.
1049 1050   *
1050 1051   * Our caller must guarantee that p cannot disappear underneath us.
1051 1052   */
1052 1053  int
1053 1054  ufcanalloc(proc_t *p, uint_t count)
1054 1055  {
1055 1056          uf_info_t *fip = P_FINFO(p);
1056 1057          int filelimit;
1057 1058          int current;
1058 1059  
1059 1060          if (count == 0)
1060 1061                  return (1);
1061 1062  
1062 1063          ASSERT(p->p_fno_ctl <= INT_MAX);
1063 1064          filelimit = (int)p->p_fno_ctl;
1064 1065  
1065 1066          mutex_enter(&fip->fi_lock);
1066 1067          current = flist_nalloc(fip);            /* # of in-use descriptors */
1067 1068          mutex_exit(&fip->fi_lock);
1068 1069  
1069 1070          /*
1070 1071           * If count is a positive integer, the worst that can happen is
1071 1072           * an overflow to a negative value, which is caught by the >= 0 check.
1072 1073           */
1073 1074          current += count;
1074 1075          if (count <= INT_MAX && current >= 0 && current <= filelimit)
1075 1076                  return (1);
1076 1077  
1077 1078          mutex_enter(&p->p_lock);
1078 1079          (void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE],
1079 1080              p->p_rctls, p, RCA_SAFE);
1080 1081          mutex_exit(&p->p_lock);
1081 1082          return (0);
1082 1083  }
1083 1084  
1084 1085  /*
1085 1086   * Allocate a user file descriptor and a file structure.
1086 1087   * Initialize the descriptor to point at the file structure.
1087 1088   * If fdp is NULL, the user file descriptor will not be allocated.
1088 1089   */
1089 1090  int
1090 1091  falloc(vnode_t *vp, int flag, file_t **fpp, int *fdp)
1091 1092  {
1092 1093          file_t *fp;
1093 1094          int fd;
1094 1095  
1095 1096          if (fdp) {
1096 1097                  if ((fd = ufalloc(0)) == -1)
1097 1098                          return (EMFILE);
1098 1099          }
1099 1100          fp = kmem_cache_alloc(file_cache, KM_SLEEP);
1100 1101          /*
1101 1102           * Note: falloc returns the fp locked
1102 1103           */
1103 1104          mutex_enter(&fp->f_tlock);
1104 1105          fp->f_count = 1;
1105 1106          fp->f_flag = (ushort_t)flag;
1106 1107          fp->f_flag2 = (flag & (FSEARCH|FEXEC)) >> 16;
1107 1108          fp->f_vnode = vp;
1108 1109          fp->f_offset = 0;
1109 1110          fp->f_audit_data = 0;
1110 1111          crhold(fp->f_cred = CRED());
1111 1112          /*
1112 1113           * allocate resources to audit_data
1113 1114           */
1114 1115          if (audit_active)
1115 1116                  audit_falloc(fp);
1116 1117          *fpp = fp;
1117 1118          if (fdp)
1118 1119                  *fdp = fd;
1119 1120          return (0);
1120 1121  }
1121 1122  
1122 1123  /*ARGSUSED*/
1123 1124  static int
1124 1125  file_cache_constructor(void *buf, void *cdrarg, int kmflags)
1125 1126  {
1126 1127          file_t *fp = buf;
1127 1128  
1128 1129          mutex_init(&fp->f_tlock, NULL, MUTEX_DEFAULT, NULL);
1129 1130          return (0);
1130 1131  }
1131 1132  
1132 1133  /*ARGSUSED*/
1133 1134  static void
1134 1135  file_cache_destructor(void *buf, void *cdrarg)
1135 1136  {
1136 1137          file_t *fp = buf;
1137 1138  
1138 1139          mutex_destroy(&fp->f_tlock);
1139 1140  }
1140 1141  
1141 1142  void
1142 1143  finit()
1143 1144  {
1144 1145          file_cache = kmem_cache_create("file_cache", sizeof (file_t), 0,
1145 1146              file_cache_constructor, file_cache_destructor, NULL, NULL, NULL, 0);
1146 1147  }
1147 1148  
1148 1149  void
1149 1150  unfalloc(file_t *fp)
1150 1151  {
1151 1152          ASSERT(MUTEX_HELD(&fp->f_tlock));
1152 1153          if (--fp->f_count <= 0) {
1153 1154                  /*
1154 1155                   * deallocate resources to audit_data
1155 1156                   */
1156 1157                  if (audit_active)
1157 1158                          audit_unfalloc(fp);
1158 1159                  crfree(fp->f_cred);
1159 1160                  mutex_exit(&fp->f_tlock);
1160 1161                  kmem_cache_free(file_cache, fp);
1161 1162          } else
1162 1163                  mutex_exit(&fp->f_tlock);
1163 1164  }
1164 1165  
1165 1166  /*
1166 1167   * Given a file descriptor, set the user's
1167 1168   * file pointer to the given parameter.
1168 1169   */
1169 1170  void
1170 1171  setf(int fd, file_t *fp)
1171 1172  {
1172 1173          uf_info_t *fip = P_FINFO(curproc);
1173 1174          uf_entry_t *ufp;
1174 1175  
1175 1176          if (AU_AUDITING())
1176 1177                  audit_setf(fp, fd);
1177 1178  
1178 1179          if (fp == NULL) {
1179 1180                  mutex_enter(&fip->fi_lock);
1180 1181                  UF_ENTER(ufp, fip, fd);
1181 1182                  fd_reserve(fip, fd, -1);
1182 1183                  mutex_exit(&fip->fi_lock);
1183 1184          } else {
1184 1185                  UF_ENTER(ufp, fip, fd);
1185 1186                  ASSERT(ufp->uf_busy);
1186 1187          }
1187 1188          ASSERT(ufp->uf_fpollinfo == NULL);
1188 1189          ASSERT(ufp->uf_flag == 0);
1189 1190          ufp->uf_file = fp;
1190 1191          cv_broadcast(&ufp->uf_wanted_cv);
1191 1192          UF_EXIT(ufp);
1192 1193  }
1193 1194  
1194 1195  /*
1195 1196   * Given a file descriptor, return the file table flags, plus,
1196 1197   * if this is a socket in asynchronous mode, the FASYNC flag.
1197 1198   * getf() may or may not have been called before calling f_getfl().
1198 1199   */
1199 1200  int
1200 1201  f_getfl(int fd, int *flagp)
1201 1202  {
1202 1203          uf_info_t *fip = P_FINFO(curproc);
1203 1204          uf_entry_t *ufp;
1204 1205          file_t *fp;
1205 1206          int error;
1206 1207  
1207 1208          if ((uint_t)fd >= fip->fi_nfiles)
1208 1209                  error = EBADF;
1209 1210          else {
1210 1211                  UF_ENTER(ufp, fip, fd);
1211 1212                  if ((fp = ufp->uf_file) == NULL)
1212 1213                          error = EBADF;
1213 1214                  else {
1214 1215                          vnode_t *vp = fp->f_vnode;
1215 1216                          int flag = fp->f_flag |
1216 1217                              ((fp->f_flag2 & ~FEPOLLED) << 16);
1217 1218  
1218 1219                          /*
1219 1220                           * BSD fcntl() FASYNC compatibility.
1220 1221                           */
1221 1222                          if (vp->v_type == VSOCK)
1222 1223                                  flag |= sock_getfasync(vp);
1223 1224                          *flagp = flag;
1224 1225                          error = 0;
1225 1226                  }
1226 1227                  UF_EXIT(ufp);
1227 1228          }
1228 1229  
1229 1230          return (error);
1230 1231  }
1231 1232  
1232 1233  /*
1233 1234   * Given a file descriptor, return the user's file flags.
1234 1235   * Force the FD_CLOEXEC flag for writable self-open /proc files.
1235 1236   * getf() may or may not have been called before calling f_getfd_error().
1236 1237   */
1237 1238  int
1238 1239  f_getfd_error(int fd, int *flagp)
1239 1240  {
1240 1241          uf_info_t *fip = P_FINFO(curproc);
1241 1242          uf_entry_t *ufp;
1242 1243          file_t *fp;
1243 1244          int flag;
1244 1245          int error;
1245 1246  
1246 1247          if ((uint_t)fd >= fip->fi_nfiles)
1247 1248                  error = EBADF;
1248 1249          else {
1249 1250                  UF_ENTER(ufp, fip, fd);
1250 1251                  if ((fp = ufp->uf_file) == NULL)
1251 1252                          error = EBADF;
1252 1253                  else {
1253 1254                          flag = ufp->uf_flag;
1254 1255                          if ((fp->f_flag & FWRITE) && pr_isself(fp->f_vnode))
1255 1256                                  flag |= FD_CLOEXEC;
1256 1257                          *flagp = flag;
1257 1258                          error = 0;
1258 1259                  }
1259 1260                  UF_EXIT(ufp);
1260 1261          }
1261 1262  
1262 1263          return (error);
1263 1264  }
1264 1265  
1265 1266  /*
1266 1267   * getf() must have been called before calling f_getfd().
1267 1268   */
1268 1269  char
1269 1270  f_getfd(int fd)
1270 1271  {
1271 1272          int flag = 0;
1272 1273          (void) f_getfd_error(fd, &flag);
1273 1274          return ((char)flag);
1274 1275  }
1275 1276  
1276 1277  /*
1277 1278   * Given a file descriptor and file flags, set the user's file flags.
1278 1279   * At present, the only valid flag is FD_CLOEXEC.
1279 1280   * getf() may or may not have been called before calling f_setfd_error().
1280 1281   */
1281 1282  int
1282 1283  f_setfd_error(int fd, int flags)
1283 1284  {
1284 1285          uf_info_t *fip = P_FINFO(curproc);
1285 1286          uf_entry_t *ufp;
1286 1287          int error;
1287 1288  
1288 1289          if ((uint_t)fd >= fip->fi_nfiles)
1289 1290                  error = EBADF;
1290 1291          else {
1291 1292                  UF_ENTER(ufp, fip, fd);
1292 1293                  if (ufp->uf_file == NULL)
1293 1294                          error = EBADF;
1294 1295                  else {
1295 1296                          ufp->uf_flag = flags & FD_CLOEXEC;
1296 1297                          error = 0;
1297 1298                  }
1298 1299                  UF_EXIT(ufp);
1299 1300          }
1300 1301          return (error);
1301 1302  }
1302 1303  
1303 1304  void
1304 1305  f_setfd(int fd, char flags)
1305 1306  {
1306 1307          (void) f_setfd_error(fd, flags);
1307 1308  }
1308 1309  
1309 1310  #define BADFD_MIN       3
1310 1311  #define BADFD_MAX       255
1311 1312  
1312 1313  /*
1313 1314   * Attempt to allocate a file descriptor which is bad and which
1314 1315   * is "poison" to the application.  It cannot be closed (except
1315 1316   * on exec), allocated for a different use, etc.
1316 1317   */
1317 1318  int
1318 1319  f_badfd(int start, int *fdp, int action)
1319 1320  {
1320 1321          int fdr;
1321 1322          int badfd;
1322 1323          uf_info_t *fip = P_FINFO(curproc);
1323 1324  
1324 1325  #ifdef _LP64
1325 1326          /* No restrictions on 64 bit _file */
1326 1327          if (get_udatamodel() != DATAMODEL_ILP32)
1327 1328                  return (EINVAL);
1328 1329  #endif
1329 1330  
1330 1331          if (start > BADFD_MAX || start < BADFD_MIN)
1331 1332                  return (EINVAL);
1332 1333  
1333 1334          if (action >= NSIG || action < 0)
1334 1335                  return (EINVAL);
1335 1336  
1336 1337          mutex_enter(&fip->fi_lock);
1337 1338          badfd = fip->fi_badfd;
1338 1339          mutex_exit(&fip->fi_lock);
1339 1340  
1340 1341          if (badfd != -1)
1341 1342                  return (EAGAIN);
1342 1343  
1343 1344          fdr = ufalloc(start);
1344 1345  
1345 1346          if (fdr > BADFD_MAX) {
1346 1347                  setf(fdr, NULL);
1347 1348                  return (EMFILE);
1348 1349          }
1349 1350          if (fdr < 0)
1350 1351                  return (EMFILE);
1351 1352  
1352 1353          mutex_enter(&fip->fi_lock);
1353 1354          if (fip->fi_badfd != -1) {
1354 1355                  /* Lost race */
1355 1356                  mutex_exit(&fip->fi_lock);
1356 1357                  setf(fdr, NULL);
1357 1358                  return (EAGAIN);
1358 1359          }
1359 1360          fip->fi_action = action;
1360 1361          fip->fi_badfd = fdr;
1361 1362          mutex_exit(&fip->fi_lock);
1362 1363          setf(fdr, NULL);
1363 1364  
1364 1365          *fdp = fdr;
1365 1366  
1366 1367          return (0);
1367 1368  }
1368 1369  
1369 1370  /*
1370 1371   * Allocate a file descriptor and assign it to the vnode "*vpp",
1371 1372   * performing the usual open protocol upon it and returning the
1372 1373   * file descriptor allocated.  It is the responsibility of the
1373 1374   * caller to dispose of "*vpp" if any error occurs.
1374 1375   */
1375 1376  int
1376 1377  fassign(vnode_t **vpp, int mode, int *fdp)
1377 1378  {
1378 1379          file_t *fp;
1379 1380          int error;
1380 1381          int fd;
1381 1382  
1382 1383          if (error = falloc((vnode_t *)NULL, mode, &fp, &fd))
1383 1384                  return (error);
1384 1385          if (error = VOP_OPEN(vpp, mode, fp->f_cred, NULL)) {
1385 1386                  setf(fd, NULL);
1386 1387                  unfalloc(fp);
1387 1388                  return (error);
1388 1389          }
1389 1390          fp->f_vnode = *vpp;
1390 1391          mutex_exit(&fp->f_tlock);
1391 1392          /*
1392 1393           * Fill in the slot falloc reserved.
1393 1394           */
1394 1395          setf(fd, fp);
1395 1396          *fdp = fd;
1396 1397          return (0);
1397 1398  }
1398 1399  
1399 1400  /*
1400 1401   * When a process forks it must increment the f_count of all file pointers
1401 1402   * since there is a new process pointing at them.  fcnt_add(fip, 1) does this.
1402 1403   * Since we are called when there is only 1 active lwp we don't need to
1403 1404   * hold fi_lock or any uf_lock.  If the fork fails, fork_fail() calls
1404 1405   * fcnt_add(fip, -1) to restore the counts.
1405 1406   */
1406 1407  void
1407 1408  fcnt_add(uf_info_t *fip, int incr)
1408 1409  {
1409 1410          int i;
1410 1411          uf_entry_t *ufp;
1411 1412          file_t *fp;
1412 1413  
1413 1414          ufp = fip->fi_list;
1414 1415          for (i = 0; i < fip->fi_nfiles; i++, ufp++) {
1415 1416                  if ((fp = ufp->uf_file) != NULL) {
1416 1417                          mutex_enter(&fp->f_tlock);
1417 1418                          ASSERT((incr == 1 && fp->f_count >= 1) ||
1418 1419                              (incr == -1 && fp->f_count >= 2));
1419 1420                          fp->f_count += incr;
1420 1421                          mutex_exit(&fp->f_tlock);
1421 1422                  }
1422 1423          }
1423 1424  }
1424 1425  
1425 1426  /*
1426 1427   * This is called from exec to close all fd's that have the FD_CLOEXEC flag
1427 1428   * set and also to close all self-open for write /proc file descriptors.
1428 1429   */
1429 1430  void
1430 1431  close_exec(uf_info_t *fip)
1431 1432  {
1432 1433          int fd;
1433 1434          file_t *fp;
1434 1435          fpollinfo_t *fpip;
1435 1436          uf_entry_t *ufp;
1436 1437          portfd_t *pfd;
1437 1438  
1438 1439          ufp = fip->fi_list;
1439 1440          for (fd = 0; fd < fip->fi_nfiles; fd++, ufp++) {
1440 1441                  if ((fp = ufp->uf_file) != NULL &&
1441 1442                      ((ufp->uf_flag & FD_CLOEXEC) ||
1442 1443                      ((fp->f_flag & FWRITE) && pr_isself(fp->f_vnode)))) {
1443 1444                          fpip = ufp->uf_fpollinfo;
1444 1445                          mutex_enter(&fip->fi_lock);
1445 1446                          mutex_enter(&ufp->uf_lock);
1446 1447                          fd_reserve(fip, fd, -1);
1447 1448                          mutex_exit(&fip->fi_lock);
1448 1449                          ufp->uf_file = NULL;
1449 1450                          ufp->uf_fpollinfo = NULL;
1450 1451                          ufp->uf_flag = 0;
1451 1452                          /*
1452 1453                           * We may need to cleanup some cached poll states
1453 1454                           * in t_pollstate before the fd can be reused. It
1454 1455                           * is important that we don't access a stale thread
1455 1456                           * structure. We will do the cleanup in two
1456 1457                           * phases to avoid deadlock and holding uf_lock for
1457 1458                           * too long. In phase 1, hold the uf_lock and call
1458 1459                           * pollblockexit() to set state in t_pollstate struct
1459 1460                           * so that a thread does not exit on us. In phase 2,
1460 1461                           * we drop the uf_lock and call pollcacheclean().
1461 1462                           */
1462 1463                          pfd = ufp->uf_portfd;
1463 1464                          ufp->uf_portfd = NULL;
1464 1465                          if (fpip != NULL)
1465 1466                                  pollblockexit(fpip);
1466 1467                          mutex_exit(&ufp->uf_lock);
1467 1468                          if (fpip != NULL)
1468 1469                                  pollcacheclean(fpip, fd);
1469 1470                          if (pfd)
1470 1471                                  port_close_fd(pfd);
1471 1472                          (void) closef(fp);
1472 1473                  }
1473 1474          }
1474 1475  
1475 1476          /* Reset bad fd */
1476 1477          fip->fi_badfd = -1;
1477 1478          fip->fi_action = -1;
1478 1479  }
1479 1480  
1480 1481  /*
1481 1482   * Utility function called by most of the *at() system call interfaces.
1482 1483   *
1483 1484   * Generate a starting vnode pointer for an (fd, path) pair where 'fd'
1484 1485   * is an open file descriptor for a directory to be used as the starting
  
    | 
      ↓ open down ↓ | 
    619 lines elided | 
    
      ↑ open up ↑ | 
  
1485 1486   * point for the lookup of the relative pathname 'path' (or, if path is
1486 1487   * NULL, generate a vnode pointer for the direct target of the operation).
1487 1488   *
1488 1489   * If we successfully return a non-NULL startvp, it has been the target
1489 1490   * of VN_HOLD() and the caller must call VN_RELE() on it.
1490 1491   */
1491 1492  int
1492 1493  fgetstartvp(int fd, char *path, vnode_t **startvpp)
1493 1494  {
1494 1495          vnode_t         *startvp;
1495      -        file_t          *startfp;
1496      -        char            startchar;
     1496 +        file_t          *startfp;
     1497 +        char            startchar;
1497 1498  
1498 1499          if (fd == AT_FDCWD && path == NULL)
1499 1500                  return (EFAULT);
1500 1501  
1501 1502          if (fd == AT_FDCWD) {
1502 1503                  /*
1503 1504                   * Start from the current working directory.
1504 1505                   */
1505 1506                  startvp = NULL;
1506 1507          } else {
1507 1508                  if (path == NULL)
1508 1509                          startchar = '\0';
1509 1510                  else if (copyin(path, &startchar, sizeof (char)))
1510 1511                          return (EFAULT);
1511 1512  
1512 1513                  if (startchar == '/') {
1513 1514                          /*
1514 1515                           * 'path' is an absolute pathname.
1515 1516                           */
1516 1517                          startvp = NULL;
1517 1518                  } else {
1518 1519                          /*
1519 1520                           * 'path' is a relative pathname or we will
1520 1521                           * be applying the operation to 'fd' itself.
1521 1522                           */
1522 1523                          if ((startfp = getf(fd)) == NULL)
1523 1524                                  return (EBADF);
1524 1525                          startvp = startfp->f_vnode;
1525 1526                          VN_HOLD(startvp);
1526 1527                          releasef(fd);
1527 1528                  }
1528 1529          }
1529 1530          *startvpp = startvp;
1530 1531          return (0);
1531 1532  }
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
1532 1533  
1533 1534  /*
1534 1535   * Called from fchownat() and fchmodat() to set ownership and mode.
1535 1536   * The contents of *vap must be set before calling here.
1536 1537   */
1537 1538  int
1538 1539  fsetattrat(int fd, char *path, int flags, struct vattr *vap)
1539 1540  {
1540 1541          vnode_t         *startvp;
1541 1542          vnode_t         *vp;
1542      -        int             error;
     1543 +        int             error;
1543 1544  
1544 1545          /*
1545 1546           * Since we are never called to set the size of a file, we don't
1546 1547           * need to check for non-blocking locks (via nbl_need_check(vp)).
1547 1548           */
1548 1549          ASSERT(!(vap->va_mask & AT_SIZE));
1549 1550  
1550 1551          if ((error = fgetstartvp(fd, path, &startvp)) != 0)
1551 1552                  return (error);
1552 1553          if (AU_AUDITING() && startvp != NULL)
1553 1554                  audit_setfsat_path(1);
1554 1555  
1555 1556          /*
1556 1557           * Do lookup for fchownat/fchmodat when path not NULL
1557 1558           */
1558 1559          if (path != NULL) {
1559 1560                  if (error = lookupnameat(path, UIO_USERSPACE,
1560 1561                      (flags == AT_SYMLINK_NOFOLLOW) ?
1561 1562                      NO_FOLLOW : FOLLOW,
1562 1563                      NULLVPP, &vp, startvp)) {
1563 1564                          if (startvp != NULL)
1564 1565                                  VN_RELE(startvp);
1565 1566                          return (error);
1566 1567                  }
1567 1568          } else {
1568 1569                  vp = startvp;
1569 1570                  ASSERT(vp);
1570 1571                  VN_HOLD(vp);
1571 1572          }
1572 1573  
1573 1574          if (vn_is_readonly(vp)) {
1574 1575                  error = EROFS;
1575 1576          } else {
1576 1577                  error = VOP_SETATTR(vp, vap, 0, CRED(), NULL);
1577 1578          }
1578 1579  
1579 1580          if (startvp != NULL)
1580 1581                  VN_RELE(startvp);
1581 1582          VN_RELE(vp);
1582 1583  
1583 1584          return (error);
1584 1585  }
1585 1586  
1586 1587  /*
1587 1588   * Return true if the given vnode is referenced by any
1588 1589   * entry in the current process's file descriptor table.
1589 1590   */
1590 1591  int
1591 1592  fisopen(vnode_t *vp)
1592 1593  {
1593 1594          int fd;
1594 1595          file_t *fp;
1595 1596          vnode_t *ovp;
1596 1597          uf_info_t *fip = P_FINFO(curproc);
1597 1598          uf_entry_t *ufp;
1598 1599  
1599 1600          mutex_enter(&fip->fi_lock);
1600 1601          for (fd = 0; fd < fip->fi_nfiles; fd++) {
1601 1602                  UF_ENTER(ufp, fip, fd);
1602 1603                  if ((fp = ufp->uf_file) != NULL &&
1603 1604                      (ovp = fp->f_vnode) != NULL && VN_CMP(vp, ovp)) {
1604 1605                          UF_EXIT(ufp);
1605 1606                          mutex_exit(&fip->fi_lock);
1606 1607                          return (1);
1607 1608                  }
1608 1609                  UF_EXIT(ufp);
1609 1610          }
1610 1611          mutex_exit(&fip->fi_lock);
1611 1612          return (0);
1612 1613  }
1613 1614  
1614 1615  /*
1615 1616   * Return zero if at least one file currently open (by curproc) shouldn't be
1616 1617   * allowed to change zones.
1617 1618   */
1618 1619  int
1619 1620  files_can_change_zones(void)
1620 1621  {
1621 1622          int fd;
1622 1623          file_t *fp;
1623 1624          uf_info_t *fip = P_FINFO(curproc);
1624 1625          uf_entry_t *ufp;
1625 1626  
1626 1627          mutex_enter(&fip->fi_lock);
1627 1628          for (fd = 0; fd < fip->fi_nfiles; fd++) {
1628 1629                  UF_ENTER(ufp, fip, fd);
1629 1630                  if ((fp = ufp->uf_file) != NULL &&
1630 1631                      !vn_can_change_zones(fp->f_vnode)) {
1631 1632                          UF_EXIT(ufp);
1632 1633                          mutex_exit(&fip->fi_lock);
1633 1634                          return (0);
1634 1635                  }
1635 1636                  UF_EXIT(ufp);
1636 1637          }
1637 1638          mutex_exit(&fip->fi_lock);
1638 1639          return (1);
1639 1640  }
1640 1641  
1641 1642  #ifdef DEBUG
1642 1643  
1643 1644  /*
1644 1645   * The following functions are only used in ASSERT()s elsewhere.
1645 1646   * They do not modify the state of the system.
1646 1647   */
1647 1648  
1648 1649  /*
1649 1650   * Return true (1) if the current thread is in the fpollinfo
1650 1651   * list for this file descriptor, else false (0).
1651 1652   */
1652 1653  static int
1653 1654  curthread_in_plist(uf_entry_t *ufp)
1654 1655  {
1655 1656          fpollinfo_t *fpip;
1656 1657  
1657 1658          ASSERT(MUTEX_HELD(&ufp->uf_lock));
1658 1659          for (fpip = ufp->uf_fpollinfo; fpip; fpip = fpip->fp_next)
1659 1660                  if (fpip->fp_thread == curthread)
1660 1661                          return (1);
1661 1662          return (0);
1662 1663  }
1663 1664  
1664 1665  /*
1665 1666   * Sanity check to make sure that after lwp_exit(),
1666 1667   * curthread does not appear on any fd's fpollinfo list.
1667 1668   */
1668 1669  void
1669 1670  checkfpollinfo(void)
1670 1671  {
1671 1672          int fd;
1672 1673          uf_info_t *fip = P_FINFO(curproc);
1673 1674          uf_entry_t *ufp;
1674 1675  
1675 1676          mutex_enter(&fip->fi_lock);
1676 1677          for (fd = 0; fd < fip->fi_nfiles; fd++) {
1677 1678                  UF_ENTER(ufp, fip, fd);
1678 1679                  ASSERT(!curthread_in_plist(ufp));
1679 1680                  UF_EXIT(ufp);
1680 1681          }
1681 1682          mutex_exit(&fip->fi_lock);
1682 1683  }
1683 1684  
1684 1685  /*
1685 1686   * Return true (1) if the current thread is in the fpollinfo
1686 1687   * list for this file descriptor, else false (0).
1687 1688   * This is the same as curthread_in_plist(),
1688 1689   * but is called w/o holding uf_lock.
1689 1690   */
1690 1691  int
1691 1692  infpollinfo(int fd)
1692 1693  {
1693 1694          uf_info_t *fip = P_FINFO(curproc);
1694 1695          uf_entry_t *ufp;
1695 1696          int rc;
1696 1697  
1697 1698          UF_ENTER(ufp, fip, fd);
1698 1699          rc = curthread_in_plist(ufp);
1699 1700          UF_EXIT(ufp);
1700 1701          return (rc);
1701 1702  }
1702 1703  
1703 1704  #endif  /* DEBUG */
1704 1705  
1705 1706  /*
1706 1707   * Add the curthread to fpollinfo list, meaning this fd is currently in the
1707 1708   * thread's poll cache. Each lwp polling this file descriptor should call
1708 1709   * this routine once.
1709 1710   */
1710 1711  void
1711 1712  addfpollinfo(int fd)
1712 1713  {
1713 1714          struct uf_entry *ufp;
1714 1715          fpollinfo_t *fpip;
1715 1716          uf_info_t *fip = P_FINFO(curproc);
1716 1717  
1717 1718          fpip = kmem_zalloc(sizeof (fpollinfo_t), KM_SLEEP);
1718 1719          fpip->fp_thread = curthread;
1719 1720          UF_ENTER(ufp, fip, fd);
1720 1721          /*
1721 1722           * Assert we are not already on the list, that is, that
1722 1723           * this lwp did not call addfpollinfo twice for the same fd.
1723 1724           */
1724 1725          ASSERT(!curthread_in_plist(ufp));
1725 1726          /*
1726 1727           * addfpollinfo is always done inside the getf/releasef pair.
1727 1728           */
1728 1729          ASSERT(ufp->uf_refcnt >= 1);
1729 1730          fpip->fp_next = ufp->uf_fpollinfo;
1730 1731          ufp->uf_fpollinfo = fpip;
1731 1732          UF_EXIT(ufp);
1732 1733  }
1733 1734  
1734 1735  /*
1735 1736   * Delete curthread from fpollinfo list if it is there.
1736 1737   */
1737 1738  void
1738 1739  delfpollinfo(int fd)
1739 1740  {
1740 1741          struct uf_entry *ufp;
1741 1742          struct fpollinfo *fpip;
1742 1743          struct fpollinfo **fpipp;
1743 1744          uf_info_t *fip = P_FINFO(curproc);
1744 1745  
1745 1746          UF_ENTER(ufp, fip, fd);
1746 1747          for (fpipp = &ufp->uf_fpollinfo;
1747 1748              (fpip = *fpipp) != NULL;
1748 1749              fpipp = &fpip->fp_next) {
1749 1750                  if (fpip->fp_thread == curthread) {
1750 1751                          *fpipp = fpip->fp_next;
1751 1752                          kmem_free(fpip, sizeof (fpollinfo_t));
1752 1753                          break;
1753 1754                  }
1754 1755          }
1755 1756          /*
1756 1757           * Assert that we are not still on the list, that is, that
1757 1758           * this lwp did not call addfpollinfo twice for the same fd.
1758 1759           */
1759 1760          ASSERT(!curthread_in_plist(ufp));
1760 1761          UF_EXIT(ufp);
1761 1762  }
1762 1763  
1763 1764  /*
1764 1765   * fd is associated with a port. pfd is a pointer to the fd entry in the
1765 1766   * cache of the port.
1766 1767   */
1767 1768  
1768 1769  void
1769 1770  addfd_port(int fd, portfd_t *pfd)
1770 1771  {
1771 1772          struct uf_entry *ufp;
1772 1773          uf_info_t *fip = P_FINFO(curproc);
1773 1774  
1774 1775          UF_ENTER(ufp, fip, fd);
1775 1776          /*
1776 1777           * addfd_port is always done inside the getf/releasef pair.
1777 1778           */
1778 1779          ASSERT(ufp->uf_refcnt >= 1);
1779 1780          if (ufp->uf_portfd == NULL) {
1780 1781                  /* first entry */
1781 1782                  ufp->uf_portfd = pfd;
1782 1783                  pfd->pfd_next = NULL;
1783 1784          } else {
1784 1785                  pfd->pfd_next = ufp->uf_portfd;
1785 1786                  ufp->uf_portfd = pfd;
1786 1787                  pfd->pfd_next->pfd_prev = pfd;
1787 1788          }
1788 1789          UF_EXIT(ufp);
1789 1790  }
1790 1791  
1791 1792  void
1792 1793  delfd_port(int fd, portfd_t *pfd)
1793 1794  {
1794 1795          struct uf_entry *ufp;
1795 1796          uf_info_t *fip = P_FINFO(curproc);
1796 1797  
1797 1798          UF_ENTER(ufp, fip, fd);
1798 1799          /*
1799 1800           * delfd_port is always done inside the getf/releasef pair.
1800 1801           */
1801 1802          ASSERT(ufp->uf_refcnt >= 1);
1802 1803          if (ufp->uf_portfd == pfd) {
1803 1804                  /* remove first entry */
1804 1805                  ufp->uf_portfd = pfd->pfd_next;
1805 1806          } else {
1806 1807                  pfd->pfd_prev->pfd_next = pfd->pfd_next;
1807 1808                  if (pfd->pfd_next != NULL)
1808 1809                          pfd->pfd_next->pfd_prev = pfd->pfd_prev;
1809 1810          }
1810 1811          UF_EXIT(ufp);
1811 1812  }
1812 1813  
1813 1814  static void
1814 1815  port_close_fd(portfd_t *pfd)
1815 1816  {
1816 1817          portfd_t        *pfdn;
1817 1818  
1818 1819          /*
1819 1820           * At this point, no other thread should access
1820 1821           * the portfd_t list for this fd. The uf_file, uf_portfd
1821 1822           * pointers in the uf_entry_t struct for this fd would
1822 1823           * be set to NULL.
1823 1824           */
1824 1825          for (; pfd != NULL; pfd = pfdn) {
1825 1826                  pfdn = pfd->pfd_next;
1826 1827                  port_close_pfd(pfd);
1827 1828          }
1828 1829  }
  
    | 
      ↓ open down ↓ | 
    276 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX