Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/fifofs/fifosubr.c
          +++ new/usr/src/uts/common/fs/fifofs/fifosubr.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  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  22   22  
  23   23  /*
  24   24   * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * The routines defined in this file are supporting routines for FIFOFS
  29   29   * file system type.
  30   30   */
  31   31  #include <sys/types.h>
  32   32  #include <sys/param.h>
  33   33  #include <sys/systm.h>
  34   34  #include <sys/debug.h>
  35   35  #include <sys/errno.h>
  36   36  #include <sys/time.h>
  37   37  #include <sys/kmem.h>
  38   38  #include <sys/inline.h>
  39   39  #include <sys/file.h>
  40   40  #include <sys/proc.h>
  41   41  #include <sys/stat.h>
  42   42  #include <sys/sysmacros.h>
  43   43  #include <sys/var.h>
  44   44  #include <sys/vfs.h>
  45   45  #include <sys/vfs_opreg.h>
  46   46  #include <sys/vnode.h>
  47   47  #include <sys/mode.h>
  48   48  #include <sys/signal.h>
  49   49  #include <sys/user.h>
  50   50  #include <sys/uio.h>
  51   51  #include <sys/flock.h>
  52   52  #include <sys/stream.h>
  53   53  #include <sys/fs/fifonode.h>
  54   54  #include <sys/strsubr.h>
  55   55  #include <sys/stropts.h>
  56   56  #include <sys/cmn_err.h>
  57   57  #include <fs/fs_subr.h>
  58   58  #include <sys/ddi.h>
  59   59  
  60   60  
  61   61  #if FIFODEBUG
  62   62  int Fifo_fastmode = 1;          /* pipes/fifos will be opened in fast mode */
  63   63  int Fifo_verbose = 0;           /* msg when switching out of fast mode */
  64   64  int Fifohiwat = FIFOHIWAT;      /* Modifiable FIFO high water mark */
  65   65  #endif
  66   66  
  67   67  /*
  68   68   * This is the loadable module wrapper.
  69   69   */
  70   70  #include <sys/modctl.h>
  71   71  
  72   72  extern struct qinit fifo_strdata;
  73   73  
  74   74  struct vfsops *fifo_vfsops;
  75   75  
  76   76  static vfsdef_t vfw = {
  77   77          VFSDEF_VERSION,
  78   78          "fifofs",
  79   79          fifoinit,
  80   80          VSW_ZMOUNT,
  81   81          NULL
  82   82  };
  83   83  
  84   84  /*
  85   85   * Module linkage information for the kernel.
  86   86   */
  87   87  extern struct mod_ops mod_fsops;
  88   88  
  89   89  static struct modlfs modlfs = {
  90   90          &mod_fsops, "filesystem for fifo", &vfw
  91   91  };
  92   92  
  93   93  static struct modlinkage modlinkage = {
  94   94          MODREV_1, (void *)&modlfs, NULL
  95   95  };
  96   96  
  97   97  int
  98   98  _init()
  99   99  {
 100  100          return (mod_install(&modlinkage));
 101  101  }
 102  102  
 103  103  int
 104  104  _info(struct modinfo *modinfop)
 105  105  {
 106  106          return (mod_info(&modlinkage, modinfop));
 107  107  }
 108  108  
 109  109  /*
 110  110   * Define data structures within this file.
 111  111   * XXX should the hash size be configurable ?
 112  112   */
 113  113  #define FIFOSHFT        5
 114  114  #define FIFO_HASHSZ     63
 115  115  
 116  116  #if ((FIFO_HASHSZ & (FIFO_HASHSZ - 1)) == 0)
 117  117  #define FIFOHASH(vp) (((uintptr_t)(vp) >> FIFOSHFT) & (FIFO_HASHSZ - 1))
 118  118  #else
 119  119  #define FIFOHASH(vp) (((uintptr_t)(vp) >> FIFOSHFT) % FIFO_HASHSZ)
 120  120  #endif
 121  121  
 122  122  fifonode_t      *fifoalloc[FIFO_HASHSZ];
 123  123  dev_t           fifodev;
 124  124  struct vfs      *fifovfsp;
 125  125  int             fifofstype;
 126  126  
 127  127  kmutex_t ftable_lock;
 128  128  static kmutex_t fino_lock;
 129  129  struct kmem_cache *fnode_cache;
 130  130  struct kmem_cache *pipe_cache;
 131  131  
 132  132  static void fifoinsert(fifonode_t *);
 133  133  static fifonode_t *fifofind(vnode_t *);
 134  134  static int fifo_connld(struct vnode **, int, cred_t *);
 135  135  static void fifo_fastturnoff(fifonode_t *);
 136  136  
 137  137  static void fifo_reinit_vp(vnode_t *);
 138  138  
 139  139  static void fnode_destructor(void *, void *);
 140  140  
 141  141  /*
 142  142   * Constructor/destructor routines for fifos and pipes.
 143  143   *
 144  144   * In the interest of code sharing, we define a common fifodata structure
 145  145   * which consists of a fifolock and one or two fnodes.  A fifo contains
 146  146   * one fnode; a pipe contains two.  The fifolock is shared by the fnodes,
 147  147   * each of which points to it:
 148  148   *
 149  149   *      --> --> ---------  --- ---
 150  150   *      |   |   | lock  |   |   |
 151  151   *      |   |   ---------   |   |
 152  152   *      |   |   |       |  fifo |
 153  153   *      |   --- | fnode |   |   |
 154  154   *      |       |       |   |  pipe
 155  155   *      |       ---------  ---  |
 156  156   *      |       |       |       |
 157  157   *      ------- | fnode |       |
 158  158   *              |       |       |
 159  159   *              ---------      ---
 160  160   *
 161  161   * Since the fifolock is at the beginning of the fifodata structure,
 162  162   * the fifolock address is the same as the fifodata address.  Thus,
 163  163   * we can determine the fifodata address from any of its member fnodes.
 164  164   * This is essential for fifo_inactive.
 165  165   *
 166  166   * The fnode constructor is designed to handle any fifodata structure,
 167  167   * deducing the number of fnodes from the total size.  Thus, the fnode
 168  168   * constructor does most of the work for the pipe constructor.
 169  169   */
 170  170  static int
 171  171  fnode_constructor(void *buf, void *cdrarg, int kmflags)
 172  172  {
 173  173          fifodata_t *fdp = buf;
 174  174          fifolock_t *flp = &fdp->fifo_lock;
 175  175          fifonode_t *fnp = &fdp->fifo_fnode[0];
 176  176          size_t size = (uintptr_t)cdrarg;
 177  177  
 178  178          mutex_init(&flp->flk_lock, NULL, MUTEX_DEFAULT, NULL);
 179  179          cv_init(&flp->flk_wait_cv, NULL, CV_DEFAULT, NULL);
 180  180          flp->flk_ocsync = 0;
 181  181  
 182  182          while ((char *)fnp < (char *)buf + size) {
 183  183  
 184  184                  vnode_t *vp;
 185  185  
 186  186                  vp = vn_alloc(kmflags);
 187  187                  if (vp == NULL) {
 188  188                          fnp->fn_vnode = NULL; /* mark for destructor */
 189  189                          fnode_destructor(buf, cdrarg);
 190  190                          return (-1);
 191  191                  }
 192  192                  fnp->fn_vnode = vp;
 193  193  
 194  194                  fnp->fn_lock = flp;
 195  195                  fnp->fn_open = 0;
 196  196                  fnp->fn_dest = fnp;
 197  197                  fnp->fn_mp = NULL;
 198  198                  fnp->fn_count = 0;
 199  199                  fnp->fn_rsynccnt = 0;
 200  200                  fnp->fn_wsynccnt = 0;
 201  201                  fnp->fn_wwaitcnt = 0;
 202  202                  fnp->fn_insync = 0;
 203  203                  fnp->fn_pcredp = NULL;
 204  204                  fnp->fn_cpid = -1;
 205  205                  /*
 206  206                   * 32-bit stat(2) may fail if fn_ino isn't initialized
 207  207                   */
 208  208                  fnp->fn_ino = 0;
 209  209  
 210  210                  cv_init(&fnp->fn_wait_cv, NULL, CV_DEFAULT, NULL);
 211  211  
 212  212                  vn_setops(vp, fifo_vnodeops);
 213  213                  vp->v_stream = NULL;
 214  214                  vp->v_type = VFIFO;
 215  215                  vp->v_data = (caddr_t)fnp;
 216  216                  vp->v_flag = VNOMAP | VNOSWAP;
 217  217                  vn_exists(vp);
 218  218                  fnp++;
 219  219          }
 220  220          return (0);
 221  221  }
 222  222  
 223  223  static void
 224  224  fnode_destructor(void *buf, void *cdrarg)
 225  225  {
 226  226          fifodata_t *fdp = buf;
 227  227          fifolock_t *flp = &fdp->fifo_lock;
 228  228          fifonode_t *fnp = &fdp->fifo_fnode[0];
 229  229          size_t size = (uintptr_t)cdrarg;
 230  230  
 231  231          mutex_destroy(&flp->flk_lock);
 232  232          cv_destroy(&flp->flk_wait_cv);
 233  233          ASSERT(flp->flk_ocsync == 0);
 234  234  
 235  235          while ((char *)fnp < (char *)buf + size) {
 236  236  
 237  237                  vnode_t *vp = FTOV(fnp);
 238  238  
 239  239                  if (vp == NULL) {
 240  240                          return; /* constructor failed here */
 241  241                  }
 242  242  
 243  243                  ASSERT(fnp->fn_mp == NULL);
 244  244                  ASSERT(fnp->fn_count == 0);
 245  245                  ASSERT(fnp->fn_lock == flp);
 246  246                  ASSERT(fnp->fn_open == 0);
 247  247                  ASSERT(fnp->fn_insync == 0);
 248  248                  ASSERT(fnp->fn_rsynccnt == 0 && fnp->fn_wsynccnt == 0);
 249  249                  ASSERT(fnp->fn_wwaitcnt == 0);
 250  250                  ASSERT(fnp->fn_pcredp == NULL);
 251  251                  ASSERT(vn_matchops(vp, fifo_vnodeops));
 252  252                  ASSERT(vp->v_stream == NULL);
 253  253                  ASSERT(vp->v_type == VFIFO);
 254  254                  ASSERT(vp->v_data == (caddr_t)fnp);
 255  255                  ASSERT((vp->v_flag & (VNOMAP|VNOSWAP)) == (VNOMAP|VNOSWAP));
 256  256  
 257  257                  cv_destroy(&fnp->fn_wait_cv);
 258  258                  vn_invalid(vp);
 259  259                  vn_free(vp);
 260  260  
 261  261                  fnp++;
 262  262          }
 263  263  }
 264  264  
 265  265  static int
 266  266  pipe_constructor(void *buf, void *cdrarg, int kmflags)
 267  267  {
 268  268          fifodata_t *fdp = buf;
 269  269          fifonode_t *fnp1 = &fdp->fifo_fnode[0];
 270  270          fifonode_t *fnp2 = &fdp->fifo_fnode[1];
 271  271          vnode_t *vp1;
 272  272          vnode_t *vp2;
 273  273  
 274  274          (void) fnode_constructor(buf, cdrarg, kmflags);
 275  275  
 276  276          vp1 = FTOV(fnp1);
 277  277          vp2 = FTOV(fnp2);
 278  278  
 279  279          vp1->v_vfsp     = vp2->v_vfsp           = fifovfsp;
 280  280          vp1->v_rdev     = vp2->v_rdev           = fifodev;
 281  281          fnp1->fn_realvp = fnp2->fn_realvp       = NULL;
 282  282          fnp1->fn_dest   = fnp2;
 283  283          fnp2->fn_dest   = fnp1;
 284  284  
 285  285          return (0);
 286  286  }
 287  287  
 288  288  static void
 289  289  pipe_destructor(void *buf, void *cdrarg)
 290  290  {
 291  291  #ifdef DEBUG
 292  292          fifodata_t *fdp = buf;
 293  293          fifonode_t *fnp1 = &fdp->fifo_fnode[0];
 294  294          fifonode_t *fnp2 = &fdp->fifo_fnode[1];
 295  295          vnode_t *vp1 = FTOV(fnp1);
 296  296          vnode_t *vp2 = FTOV(fnp2);
 297  297  
 298  298          ASSERT(vp1->v_vfsp == fifovfsp);
 299  299          ASSERT(vp2->v_vfsp == fifovfsp);
 300  300          ASSERT(vp1->v_rdev == fifodev);
 301  301          ASSERT(vp2->v_rdev == fifodev);
 302  302  #endif
 303  303          fnode_destructor(buf, cdrarg);
 304  304  }
 305  305  
 306  306  /*
 307  307   * Reinitialize a FIFO vnode (uses normal vnode reinit, but ensures that
 308  308   * vnode type and flags are reset).
 309  309   */
 310  310  
 311  311  static void fifo_reinit_vp(vnode_t *vp)
 312  312  {
 313  313          vn_reinit(vp);
 314  314          vp->v_type = VFIFO;
 315  315          vp->v_flag &= VROOT;
 316  316          vp->v_flag |= VNOMAP | VNOSWAP;
 317  317  }
 318  318  
 319  319  /*
 320  320   * Save file system type/index, initialize vfs operations vector, get
 321  321   * unique device number for FIFOFS and initialize the FIFOFS hash.
 322  322   * Create and initialize a "generic" vfs pointer that will be placed
 323  323   * in the v_vfsp field of each pipe's vnode.
 324  324   */
 325  325  int
 326  326  fifoinit(int fstype, char *name)
 327  327  {
 328  328          static const fs_operation_def_t fifo_vfsops_template[] = {
 329  329                  NULL, NULL
 330  330          };
 331  331          int error;
 332  332          major_t dev;
 333  333  
 334  334          fifofstype = fstype;
 335  335          error = vfs_setfsops(fstype, fifo_vfsops_template, &fifo_vfsops);
 336  336          if (error != 0) {
 337  337                  cmn_err(CE_WARN, "fifoinit: bad vfs ops template");
 338  338                  return (error);
 339  339          }
 340  340  
 341  341          error = vn_make_ops(name, fifo_vnodeops_template, &fifo_vnodeops);
 342  342          if (error != 0) {
 343  343                  (void) vfs_freevfsops_by_type(fstype);
 344  344                  cmn_err(CE_WARN, "fifoinit: bad vnode ops template");
 345  345                  return (error);
 346  346          }
 347  347  
 348  348          if ((dev = getudev()) == (major_t)-1) {
 349  349                  cmn_err(CE_WARN, "fifoinit: can't get unique device number");
 350  350                  dev = 0;
 351  351          }
 352  352          fifodev = makedevice(dev, 0);
 353  353  
 354  354          fifovfsp = kmem_zalloc(sizeof (struct vfs), KM_SLEEP);
 355  355          fifovfsp->vfs_next = NULL;
 356  356          vfs_setops(fifovfsp, fifo_vfsops);
 357  357          fifovfsp->vfs_vnodecovered = NULL;
 358  358          fifovfsp->vfs_flag = 0;
 359  359          fifovfsp->vfs_bsize = 1024;
 360  360          fifovfsp->vfs_fstype = fifofstype;
 361  361          vfs_make_fsid(&fifovfsp->vfs_fsid, fifodev, fifofstype);
 362  362          fifovfsp->vfs_data = NULL;
 363  363          fifovfsp->vfs_dev = fifodev;
 364  364          fifovfsp->vfs_bcount = 0;
 365  365  
 366  366          /*
 367  367           * It is necessary to initialize vfs_count here to 1.
 368  368           * This prevents the fifovfsp from getting freed when
 369  369           * a thread does a VFS_HOLD followed by a VFS_RELE
 370  370           * on the fifovfsp
 371  371           *
 372  372           * The fifovfsp should never be freed.
 373  373           */
 374  374          fifovfsp->vfs_count = 1;
 375  375  
 376  376          mutex_init(&ftable_lock, NULL, MUTEX_DEFAULT, NULL);
 377  377          mutex_init(&fino_lock, NULL, MUTEX_DEFAULT, NULL);
 378  378  
 379  379          /*
 380  380           * vnodes are cached aligned
 381  381           */
 382  382          fnode_cache = kmem_cache_create("fnode_cache",
 383  383              sizeof (fifodata_t) - sizeof (fifonode_t), 32,
 384  384              fnode_constructor, fnode_destructor, NULL,
 385  385              (void *)(sizeof (fifodata_t) - sizeof (fifonode_t)), NULL, 0);
 386  386  
 387  387          pipe_cache = kmem_cache_create("pipe_cache", sizeof (fifodata_t), 32,
 388  388              pipe_constructor, pipe_destructor, NULL,
 389  389              (void *)(sizeof (fifodata_t)), NULL, 0);
 390  390  
 391  391  #if FIFODEBUG
 392  392          if (Fifohiwat < FIFOHIWAT)
 393  393                  Fifohiwat = FIFOHIWAT;
 394  394  #endif /* FIFODEBUG */
 395  395          fifo_strdata.qi_minfo->mi_hiwat = Fifohiwat;
 396  396  
 397  397          return (0);
 398  398  }
 399  399  
 400  400  /*
 401  401   * Provide a shadow for a vnode.  We create a new shadow before checking for an
 402  402   * existing one, to minimize the amount of time we need to hold ftable_lock.
 403  403   * If a vp already has a shadow in the hash list, return its shadow.  If not,
 404  404   * we hash the new vnode and return its pointer to the caller.
 405  405   */
 406  406  vnode_t *
 407  407  fifovp(vnode_t *vp, cred_t *crp)
 408  408  {
 409  409          fifonode_t *fnp;
 410  410          fifonode_t *spec_fnp;   /* Speculative fnode ptr. */
 411  411          fifodata_t *fdp;
 412  412          vnode_t *newvp;
 413  413          struct vattr va;
 414  414          vnode_t *rvp;
 415  415  
 416  416          ASSERT(vp != NULL);
 417  417  
 418  418          fdp = kmem_cache_alloc(fnode_cache, KM_SLEEP);
 419  419  
 420  420          fdp->fifo_lock.flk_ref = 1;
 421  421          fnp = &fdp->fifo_fnode[0];
 422  422  
 423  423          /*
 424  424           * Its possible that fifo nodes on different lofs mountpoints
 425  425           * shadow the same real filesystem fifo node.
 426  426           * In this case its necessary to get and store the realvp.
 427  427           * This way different fifo nodes sharing the same real vnode
 428  428           * can use realvp for communication.
 429  429           */
 430  430  
 431  431          if (VOP_REALVP(vp, &rvp, NULL) == 0)
 432  432                          vp = rvp;
 433  433  
 434  434          fnp->fn_realvp  = vp;
 435  435          fnp->fn_wcnt    = 0;
 436  436          fnp->fn_rcnt    = 0;
 437  437  
 438  438  #if FIFODEBUG
 439  439          if (! Fifo_fastmode) {
 440  440                  fnp->fn_flag    = 0;
 441  441          } else {
 442  442                  fnp->fn_flag    = FIFOFAST;
 443  443          }
 444  444  #else /* FIFODEBUG */
 445  445          fnp->fn_flag    = FIFOFAST;
 446  446  #endif /* FIFODEBUG */
 447  447  
 448  448          /*
 449  449           * initialize the times from vp.
 450  450           */
 451  451          va.va_mask = AT_TIMES;
 452  452          if (VOP_GETATTR(vp, &va, 0, crp, NULL) == 0) {
 453  453                  fnp->fn_atime = va.va_atime.tv_sec;
 454  454                  fnp->fn_mtime = va.va_mtime.tv_sec;
 455  455                  fnp->fn_ctime = va.va_ctime.tv_sec;
 456  456          } else {
 457  457                  fnp->fn_atime = 0;
 458  458                  fnp->fn_mtime = 0;
 459  459                  fnp->fn_ctime = 0;
 460  460          }
 461  461  
 462  462          /*
 463  463           * Grab the VP here to avoid holding locks
 464  464           * whilst trying to acquire others.
 465  465           */
 466  466  
 467  467          VN_HOLD(vp);
 468  468  
 469  469          mutex_enter(&ftable_lock);
 470  470  
 471  471          if ((spec_fnp = fifofind(vp)) != NULL) {
 472  472                  mutex_exit(&ftable_lock);
 473  473  
 474  474                  /*
 475  475                   * Release the vnode and free up our pre-prepared fnode.
 476  476                   * Zero the lock reference just to explicitly signal
 477  477                   * this is unused.
 478  478                   */
 479  479                  VN_RELE(vp);
 480  480                  fdp->fifo_lock.flk_ref = 0;
 481  481                  kmem_cache_free(fnode_cache, fdp);
 482  482  
 483  483                  return (FTOV(spec_fnp));
 484  484          }
 485  485  
 486  486          newvp = FTOV(fnp);
 487  487          fifo_reinit_vp(newvp);
 488  488          /*
 489  489           * Since the fifo vnode's v_vfsp needs to point to the
 490  490           * underlying filesystem's vfsp we need to bump up the
 491  491           * underlying filesystem's vfs reference count.
 492  492           * The count is decremented when the fifo node is
 493  493           * inactivated.
 494  494           */
 495  495  
 496  496          VFS_HOLD(vp->v_vfsp);
 497  497          newvp->v_vfsp = vp->v_vfsp;
 498  498          newvp->v_rdev = vp->v_rdev;
 499  499          newvp->v_flag |= (vp->v_flag & VROOT);
 500  500  
 501  501          fifoinsert(fnp);
 502  502          mutex_exit(&ftable_lock);
 503  503  
 504  504          return (newvp);
 505  505  }
 506  506  
 507  507  /*
 508  508   * Create a pipe end by...
 509  509   * allocating a vnode-fifonode pair and initializing the fifonode.
 510  510   */
 511  511  void
 512  512  makepipe(vnode_t **vpp1, vnode_t **vpp2)
 513  513  {
 514  514          fifonode_t *fnp1;
 515  515          fifonode_t *fnp2;
 516  516          vnode_t *nvp1;
 517  517          vnode_t *nvp2;
 518  518          fifodata_t *fdp;
 519  519          time_t now;
 520  520  
 521  521          fdp = kmem_cache_alloc(pipe_cache, KM_SLEEP);
 522  522          fdp->fifo_lock.flk_ref = 2;
 523  523          fnp1 = &fdp->fifo_fnode[0];
 524  524          fnp2 = &fdp->fifo_fnode[1];
 525  525  
 526  526          fnp1->fn_wcnt   = fnp2->fn_wcnt         = 1;
 527  527          fnp1->fn_rcnt   = fnp2->fn_rcnt         = 1;
 528  528  #if FIFODEBUG
 529  529          if (! Fifo_fastmode) {
 530  530                  fnp1->fn_flag   = fnp2->fn_flag         = ISPIPE;
 531  531          } else {
 532  532                  fnp1->fn_flag   = fnp2->fn_flag         = ISPIPE | FIFOFAST;
 533  533          }
 534  534  #else /* FIFODEBUG */
 535  535          fnp1->fn_flag   = fnp2->fn_flag         = ISPIPE | FIFOFAST;
 536  536  #endif /* FIFODEBUG */
 537  537          now = gethrestime_sec();
 538  538          fnp1->fn_atime  = fnp2->fn_atime        = now;
 539  539          fnp1->fn_mtime  = fnp2->fn_mtime        = now;
 540  540          fnp1->fn_ctime  = fnp2->fn_ctime        = now;
 541  541  
 542  542          *vpp1 = nvp1 = FTOV(fnp1);
 543  543          *vpp2 = nvp2 = FTOV(fnp2);
 544  544  
 545  545          fifo_reinit_vp(nvp1);           /* Reinitialize vnodes for reuse... */
 546  546          fifo_reinit_vp(nvp2);
 547  547          nvp1->v_vfsp = fifovfsp;        /* Need to re-establish VFS & device */
 548  548          nvp2->v_vfsp = fifovfsp;        /* before we can reuse this vnode. */
 549  549          nvp1->v_rdev = fifodev;
 550  550          nvp2->v_rdev = fifodev;
 551  551  }
 552  552  
 553  553  /*
 554  554   * Attempt to establish a unique pipe id.  Only un-named pipes use this
 555  555   * routine.
 556  556   */
 557  557  ino_t
 558  558  fifogetid(void)
 559  559  {
 560  560          static ino_t fifo_ino = 0;
 561  561          ino_t fino;
 562  562  
 563  563          mutex_enter(&fino_lock);
 564  564          fino = fifo_ino++;
 565  565          mutex_exit(&fino_lock);
 566  566          return (fino);
 567  567  }
 568  568  
 569  569  
 570  570  /*
 571  571   * Stream a pipe/FIFO.
 572  572   * The FIFOCONNLD flag is used when CONNLD has been pushed on the stream.
 573  573   * If the flag is set, a new vnode is created by calling fifo_connld().
 574  574   * Connld logic was moved to fifo_connld() to speed up the open
 575  575   * operation, simplify the connld/fifo interaction, and remove inherent
 576  576   * race conditions between the connld module and fifos.
 577  577   * This routine is single threaded for two reasons.
 578  578   * 1) connld requests are synchronous; that is, they must block
 579  579   *    until the server does an I_RECVFD (oh, well).  Single threading is
 580  580   *    the simplest way to accomplish this.
 581  581   * 2) fifo_close() must not send M_HANGUP or M_ERROR while we are
 582  582   *    in stropen. Stropen() has a tendency to reset things and
 583  583   *    we would like streams to remember that a hangup occurred.
 584  584   */
 585  585  int
 586  586  fifo_stropen(vnode_t **vpp, int flag, cred_t *crp, int dotwist, int lockheld)
 587  587  {
 588  588          int error = 0;
 589  589          vnode_t *oldvp = *vpp;
 590  590          fifonode_t *fnp = VTOF(*vpp);
 591  591          dev_t pdev = 0;
 592  592          int firstopen = 0;
 593  593          fifolock_t *fn_lock;
 594  594  
 595  595          fn_lock = fnp->fn_lock;
 596  596          if (!lockheld)
 597  597                  mutex_enter(&fn_lock->flk_lock);
 598  598          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
 599  599  
 600  600          /*
 601  601           * FIFO is in the process of opening. Wait for it
 602  602           * to complete before starting another open on it
 603  603           * This prevents races associated with connld open
 604  604           */
 605  605          while (fnp->fn_flag & FIFOOPEN) {
 606  606                  if (!cv_wait_sig(&fnp->fn_wait_cv, &fn_lock->flk_lock)) {
 607  607                          fifo_cleanup(oldvp, flag);
 608  608                          if (!lockheld)
 609  609                                  mutex_exit(&fn_lock->flk_lock);
 610  610                          return (EINTR);
 611  611                  }
 612  612          }
 613  613  
 614  614          /*
 615  615           * The other end of the pipe is almost closed so
 616  616           * reject any other open on this end of the pipe
 617  617           * This normally only happens with a pipe mounted under namefs, but
 618  618           * we can also see an open via proc/fd, which should still succeed.
 619  619           * To indicate the proc/fd case the FKLYR flag is passed.
 620  620           */
 621  621          if ((fnp->fn_flag & (FIFOCLOSE|ISPIPE)) == (FIFOCLOSE|ISPIPE) &&
 622  622              (flag & FKLYR) == 0) {
 623  623                  fifo_cleanup(oldvp, flag);
 624  624                  cv_broadcast(&fnp->fn_wait_cv);
 625  625                  if (!lockheld)
 626  626                          mutex_exit(&fn_lock->flk_lock);
 627  627                  return (ENXIO);
 628  628          }
 629  629  
 630  630          fnp->fn_flag |= FIFOOPEN;
 631  631  
 632  632          /*
 633  633           * can't allow close to happen while we are
 634  634           * in the middle of stropen().
 635  635           * M_HANGUP and M_ERROR could leave the stream in a strange state
 636  636           */
 637  637          while (fn_lock->flk_ocsync)
 638  638                  cv_wait(&fn_lock->flk_wait_cv, &fn_lock->flk_lock);
 639  639  
 640  640          fn_lock->flk_ocsync = 1;
 641  641  
 642  642          if (fnp->fn_flag & FIFOCONNLD) {
 643  643                  /*
 644  644                   * This is a reopen, so we should release the fifo lock
 645  645                   * just in case some strange module pushed on connld
 646  646                   * has some odd side effect.
 647  647                   * Note: this stropen is on the oldvp.  It will
 648  648                   * have no impact on the connld vp returned and
 649  649                   * strclose() will only be called when we release
 650  650                   * flk_ocsync
 651  651                   */
 652  652                  mutex_exit(&fn_lock->flk_lock);
 653  653                  if ((error = stropen(oldvp, &pdev, flag, crp)) != 0) {
 654  654                          mutex_enter(&fn_lock->flk_lock);
 655  655                          fifo_cleanup(oldvp, flag);
 656  656                          fn_lock->flk_ocsync = 0;
 657  657                          cv_broadcast(&fn_lock->flk_wait_cv);
 658  658                          goto out;
 659  659                  }
 660  660                  /*
 661  661                   * streams open done, allow close on other end if
 662  662                   * required.  Do this now.. it could
 663  663                   * be a very long time before fifo_connld returns.
 664  664                   */
 665  665                  mutex_enter(&fn_lock->flk_lock);
 666  666                  /*
 667  667                   * we need to fake an open here so that if this
 668  668                   * end of the pipe closes, we don't loose the
 669  669                   * stream head (kind of like single threading
 670  670                   * open and close for this end of the pipe)
 671  671                   * We'll need to call fifo_close() to do clean
 672  672                   * up in case this end of the pipe was closed
 673  673                   * down while we were in fifo_connld()
 674  674                   */
 675  675                  ASSERT(fnp->fn_open > 0);
 676  676                  fnp->fn_open++;
 677  677                  fn_lock->flk_ocsync = 0;
 678  678                  cv_broadcast(&fn_lock->flk_wait_cv);
 679  679                  mutex_exit(&fn_lock->flk_lock);
 680  680                  /*
 681  681                   * Connld has been pushed onto the pipe
 682  682                   * Create new pipe on behalf of connld
 683  683                   */
 684  684                  if (error = fifo_connld(vpp, flag, crp)) {
 685  685                          (void) fifo_close(oldvp, flag, 1, 0, crp, NULL);
 686  686                          mutex_enter(&fn_lock->flk_lock);
 687  687                          goto out;
 688  688                  }
 689  689                  /*
 690  690                   * undo fake open.  We need to call fifo_close
 691  691                   * because some other thread could have done
 692  692                   * a close and detach of the named pipe while
 693  693                   * we were in fifo_connld(), so
 694  694                   * we want to make sure the close completes (yuk)
 695  695                   */
 696  696                  (void) fifo_close(oldvp, flag, 1, 0, crp, NULL);
 697  697                  /*
 698  698                   * fifo_connld has changed the vp, so we
 699  699                   * need to re-initialize locals
 700  700                   */
 701  701                  fnp = VTOF(*vpp);
 702  702                  fn_lock = fnp->fn_lock;
 703  703                  mutex_enter(&fn_lock->flk_lock);
 704  704          } else {
 705  705                  /*
 706  706                   * release lock in case there are modules pushed that
 707  707                   * could have some strange side effect
 708  708                   */
 709  709  
 710  710                  mutex_exit(&fn_lock->flk_lock);
 711  711  
 712  712                  /*
 713  713                   * If this is the first open of a fifo (dotwist
 714  714                   * will be non-zero) we will need to twist the queues.
 715  715                   */
 716  716                  if (oldvp->v_stream == NULL)
 717  717                          firstopen = 1;
 718  718  
 719  719  
 720  720                  /*
 721  721                   * normal open of pipe/fifo
 722  722                   */
 723  723  
 724  724                  if ((error = stropen(oldvp, &pdev, flag, crp)) != 0) {
 725  725                          mutex_enter(&fn_lock->flk_lock);
 726  726                          fifo_cleanup(oldvp, flag);
 727  727                          ASSERT(fnp->fn_open != 0 || oldvp->v_stream == NULL);
 728  728                          fn_lock->flk_ocsync = 0;
 729  729                          cv_broadcast(&fn_lock->flk_wait_cv);
 730  730                          goto out;
 731  731                  }
 732  732                  mutex_enter(&fn_lock->flk_lock);
 733  733  
 734  734                  /*
 735  735                   * twist the ends of the fifo together
 736  736                   */
 737  737                  if (dotwist && firstopen)
 738  738                          strmate(*vpp, *vpp);
 739  739  
 740  740                  /*
 741  741                   * Show that this open has succeeded
 742  742                   * and allow closes or other opens to proceed
 743  743                   */
 744  744                  fnp->fn_open++;
 745  745                  fn_lock->flk_ocsync = 0;
 746  746                  cv_broadcast(&fn_lock->flk_wait_cv);
 747  747          }
 748  748  out:
 749  749          fnp->fn_flag &= ~FIFOOPEN;
 750  750          if (error == 0) {
 751  751                  fnp->fn_flag |= FIFOISOPEN;
 752  752                  /*
 753  753                   * If this is a FIFO and has the close flag set
 754  754                   * and there are now writers, clear the close flag
 755  755                   * Note: close flag only gets set when last writer
 756  756                   * on a FIFO goes away.
 757  757                   */
 758  758                  if (((fnp->fn_flag & (ISPIPE|FIFOCLOSE)) == FIFOCLOSE) &&
 759  759                      fnp->fn_wcnt > 0)
 760  760                          fnp->fn_flag &= ~FIFOCLOSE;
 761  761          }
 762  762          cv_broadcast(&fnp->fn_wait_cv);
 763  763          if (!lockheld)
 764  764                  mutex_exit(&fn_lock->flk_lock);
 765  765          return (error);
 766  766  }
 767  767  
 768  768  /*
 769  769   * Clean up the state of a FIFO and/or mounted pipe in the
 770  770   * event that a fifo_open() was interrupted while the
 771  771   * process was blocked.
 772  772   */
 773  773  void
 774  774  fifo_cleanup(vnode_t *vp, int flag)
 775  775  {
 776  776          fifonode_t *fnp = VTOF(vp);
 777  777  
 778  778          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
 779  779  
 780  780          cleanlocks(vp, curproc->p_pid, 0);
 781  781          cleanshares(vp, curproc->p_pid);
 782  782          if (flag & FREAD) {
 783  783                  fnp->fn_rcnt--;
 784  784          }
 785  785          if (flag & FWRITE) {
 786  786                  fnp->fn_wcnt--;
 787  787          }
 788  788          cv_broadcast(&fnp->fn_wait_cv);
 789  789  }
 790  790  
 791  791  
 792  792  /*
 793  793   * Insert a fifonode-vnode pair onto the fifoalloc hash list.
 794  794   */
 795  795  static void
 796  796  fifoinsert(fifonode_t *fnp)
 797  797  {
 798  798          int idx = FIFOHASH(fnp->fn_realvp);
 799  799  
 800  800          /*
 801  801           * We don't need to hold fn_lock since we're holding ftable_lock and
 802  802           * this routine is only called right after we've allocated an fnode.
 803  803           * FIFO is inserted at head of NULL terminated doubly linked list.
 804  804           */
 805  805  
 806  806          ASSERT(MUTEX_HELD(&ftable_lock));
 807  807          fnp->fn_backp = NULL;
 808  808          fnp->fn_nextp = fifoalloc[idx];
 809  809          fifoalloc[idx] = fnp;
 810  810          if (fnp->fn_nextp)
 811  811                  fnp->fn_nextp->fn_backp = fnp;
 812  812  }
 813  813  
 814  814  /*
 815  815   * Find a fifonode-vnode pair on the fifoalloc hash list.
 816  816   * vp is a vnode to be shadowed. If it's on the hash list,
 817  817   * it already has a shadow, therefore return its corresponding
 818  818   * fifonode.
 819  819   */
 820  820  static fifonode_t *
 821  821  fifofind(vnode_t *vp)
 822  822  {
 823  823          fifonode_t *fnode;
 824  824  
 825  825          ASSERT(MUTEX_HELD(&ftable_lock));
 826  826          for (fnode = fifoalloc[FIFOHASH(vp)]; fnode; fnode = fnode->fn_nextp) {
 827  827                  if (fnode->fn_realvp == vp) {
 828  828                          VN_HOLD(FTOV(fnode));
 829  829                          return (fnode);
 830  830                  }
 831  831          }
 832  832          return (NULL);
 833  833  }
 834  834  
 835  835  /*
 836  836   * Remove a fifonode-vnode pair from the fifoalloc hash list.
 837  837   * This routine is called from the fifo_inactive() routine when a
 838  838   * FIFO is being released.
 839  839   * If the link to be removed is the only link, set fifoalloc to NULL.
 840  840   */
 841  841  void
 842  842  fiforemove(fifonode_t *fnp)
 843  843  {
 844  844          int idx = FIFOHASH(fnp->fn_realvp);
 845  845          fifonode_t *fnode;
 846  846  
 847  847          ASSERT(MUTEX_HELD(&ftable_lock));
 848  848          fnode = fifoalloc[idx];
 849  849          /*
 850  850           * fast path... only 1 FIFO in this list entry
 851  851           */
 852  852          if (fnode != NULL && fnode == fnp &&
 853  853              !fnode->fn_nextp && !fnode->fn_backp) {
 854  854                  fifoalloc[idx] = NULL;
 855  855          } else {
 856  856  
 857  857                  for (;  fnode;  fnode = fnode->fn_nextp) {
 858  858                          if (fnode == fnp) {
 859  859                                  /*
 860  860                                   * if we are first entry
 861  861                                   */
 862  862                                  if (fnp == fifoalloc[idx])
 863  863                                          fifoalloc[idx] = fnp->fn_nextp;
 864  864                                  if (fnode->fn_nextp)
 865  865                                          fnode->fn_nextp->fn_backp =
 866  866                                              fnode->fn_backp;
 867  867                                  if (fnode->fn_backp)
 868  868                                          fnode->fn_backp->fn_nextp =
 869  869                                              fnode->fn_nextp;
 870  870                                  break;
 871  871                          }
 872  872                  }
 873  873          }
 874  874  }
 875  875  
 876  876  /*
 877  877   * Flush all data from a fifo's message queue
 878  878   */
 879  879  
 880  880  void
 881  881  fifo_fastflush(fifonode_t *fnp)
 882  882  {
 883  883          mblk_t *bp;
 884  884          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
 885  885  
 886  886          if ((bp = fnp->fn_mp) != NULL) {
 887  887                  fnp->fn_mp = NULL;
 888  888                  fnp->fn_count = 0;
 889  889                  freemsg(bp);
 890  890          }
 891  891          fifo_wakewriter(fnp->fn_dest, fnp->fn_lock);
 892  892  }
 893  893  
 894  894  /*
 895  895   * Note:  This routine is single threaded
 896  896   *  Protected by FIFOOPEN flag (i.e. flk_lock is not held)
 897  897   *  Upon successful completion, the original fifo is unlocked
 898  898   *  and FIFOOPEN is cleared for the original vpp.
 899  899   *  The new fifo returned has FIFOOPEN set.
 900  900   */
 901  901  static int
 902  902  fifo_connld(struct vnode **vpp, int flag, cred_t *crp)
 903  903  {
 904  904          struct vnode *vp1;
 905  905          struct vnode *vp2;
 906  906          struct fifonode *oldfnp;
 907  907          struct fifonode *fn_dest;
 908  908          int error;
 909  909          struct file *filep;
 910  910          struct fifolock *fn_lock;
 911  911          cred_t *c;
 912  912  
 913  913          /*
 914  914           * Get two vnodes that will represent the pipe ends for the new pipe.
 915  915           */
 916  916          makepipe(&vp1, &vp2);
 917  917  
 918  918          /*
 919  919           * Allocate a file descriptor and file pointer for one of the pipe
 920  920           * ends. The file descriptor will be used to send that pipe end to
 921  921           * the process on the other end of this stream. Note that we get
 922  922           * the file structure only, there is no file list entry allocated.
 923  923           */
 924  924          if (error = falloc(vp1, FWRITE|FREAD, &filep, NULL)) {
 925  925                  VN_RELE(vp1);
 926  926                  VN_RELE(vp2);
 927  927                  return (error);
 928  928          }
 929  929          mutex_exit(&filep->f_tlock);
 930  930          oldfnp = VTOF(*vpp);
 931  931          fn_lock = oldfnp->fn_lock;
 932  932          fn_dest = oldfnp->fn_dest;
 933  933  
 934  934          /*
 935  935           * Create two new stream heads and attach them to the two vnodes for
 936  936           * the new pipe.
 937  937           */
 938  938          if ((error = fifo_stropen(&vp1, FREAD|FWRITE, filep->f_cred, 0, 0)) !=
 939  939              0 ||
 940  940              (error = fifo_stropen(&vp2, flag, filep->f_cred, 0, 0)) != 0) {
 941  941  #if DEBUG
 942  942                  cmn_err(CE_NOTE, "fifo stropen failed error 0x%x", error);
 943  943  #endif
 944  944                  /*
 945  945                   * this will call fifo_close and VN_RELE on vp1
 946  946                   */
 947  947                  (void) closef(filep);
 948  948                  VN_RELE(vp2);
 949  949                  return (error);
 950  950          }
 951  951  
 952  952          /*
 953  953           * twist the ends of the pipe together
 954  954           */
 955  955          strmate(vp1, vp2);
 956  956  
 957  957          /*
 958  958           * Set our end to busy in open
 959  959           * Note: Don't need lock around this because we're the only
 960  960           * one who knows about it
 961  961           */
 962  962          VTOF(vp2)->fn_flag |= FIFOOPEN;
 963  963  
 964  964          mutex_enter(&fn_lock->flk_lock);
 965  965  
 966  966          fn_dest->fn_flag |= FIFOSEND;
 967  967          /*
 968  968           * check to make sure neither end of pipe has gone away
 969  969           */
 970  970          if (!(fn_dest->fn_flag & FIFOISOPEN)) {
 971  971                  error = ENXIO;
 972  972                  fn_dest->fn_flag &= ~FIFOSEND;
 973  973                  mutex_exit(&fn_lock->flk_lock);
 974  974                  /*
 975  975                   * this will call fifo_close and VN_RELE on vp1
 976  976                   */
 977  977                  goto out;
 978  978          }
 979  979          mutex_exit(&fn_lock->flk_lock);
 980  980  
 981  981          /*
 982  982           * Tag the sender's credential on the pipe descriptor.
 983  983           */
 984  984          crhold(VTOF(vp1)->fn_pcredp = crp);
 985  985          VTOF(vp1)->fn_cpid = curproc->p_pid;
 986  986  
 987  987          /*
 988  988           * send the file descriptor to other end of pipe
 989  989           */
 990  990          if (error = do_sendfp((*vpp)->v_stream, filep, crp)) {
 991  991                  mutex_enter(&fn_lock->flk_lock);
 992  992                  fn_dest->fn_flag &= ~FIFOSEND;
 993  993                  mutex_exit(&fn_lock->flk_lock);
 994  994                  /*
 995  995                   * this will call fifo_close and VN_RELE on vp1
 996  996                   */
 997  997                  goto out;
 998  998          }
 999  999  
1000 1000          mutex_enter(&fn_lock->flk_lock);
1001 1001          /*
1002 1002           * Wait for other end to receive file descriptor
1003 1003           * FIFOCLOSE indicates that one or both sides of the pipe
1004 1004           * have gone away.
1005 1005           */
1006 1006          while ((fn_dest->fn_flag & (FIFOCLOSE | FIFOSEND)) == FIFOSEND) {
1007 1007                  if (!cv_wait_sig(&oldfnp->fn_wait_cv, &fn_lock->flk_lock)) {
1008 1008                          error = EINTR;
1009 1009                          fn_dest->fn_flag &= ~FIFOSEND;
1010 1010                          mutex_exit(&fn_lock->flk_lock);
1011 1011                          goto out;
1012 1012                  }
1013 1013          }
1014 1014          /*
1015 1015           * If either end of pipe has gone away and the other end did not
1016 1016           * receive pipe, reject the connld open
1017 1017           */
1018 1018          if ((fn_dest->fn_flag & FIFOSEND)) {
1019 1019                  error = ENXIO;
1020 1020                  fn_dest->fn_flag &= ~FIFOSEND;
1021 1021                  mutex_exit(&fn_lock->flk_lock);
1022 1022                  goto out;
1023 1023          }
1024 1024  
1025 1025          oldfnp->fn_flag &= ~FIFOOPEN;
1026 1026          cv_broadcast(&oldfnp->fn_wait_cv);
1027 1027          mutex_exit(&fn_lock->flk_lock);
1028 1028  
1029 1029          VN_RELE(*vpp);
1030 1030          *vpp = vp2;
1031 1031          (void) closef(filep);
1032 1032          return (0);
1033 1033  out:
1034 1034          c = filep->f_cred;
1035 1035          crhold(c);
1036 1036          (void) closef(filep);
1037 1037          VTOF(vp2)->fn_flag &= ~FIFOOPEN;
1038 1038          (void) fifo_close(vp2, flag, 1, (offset_t)0, c, NULL);
1039 1039          crfree(c);
1040 1040          VN_RELE(vp2);
1041 1041          return (error);
1042 1042  }
1043 1043  
1044 1044  /*
1045 1045   * Disable fastpath mode.
1046 1046   */
1047 1047  void
1048 1048  fifo_fastoff(fifonode_t *fnp)
1049 1049  {
1050 1050          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
1051 1051          ASSERT(FTOV(fnp)->v_stream);
1052 1052  
1053 1053          /* FIFOSTAYFAST is set => FIFOFAST is set */
1054 1054          while ((fnp->fn_flag & FIFOSTAYFAST) || ((fnp->fn_flag & ISPIPE) &&
1055 1055              (fnp->fn_dest->fn_flag & FIFOSTAYFAST))) {
1056 1056                  ASSERT(fnp->fn_flag & FIFOFAST);
1057 1057                  /* indicate someone is waiting to turn into stream mode */
1058 1058                  fnp->fn_flag |= FIFOWAITMODE;
1059 1059                  cv_wait(&fnp->fn_wait_cv, &fnp->fn_lock->flk_lock);
1060 1060                  fnp->fn_flag &= ~FIFOWAITMODE;
1061 1061          }
1062 1062  
1063 1063          /* as we may have relased the lock, test the FIFOFAST flag here */
1064 1064          if (!(fnp->fn_flag & FIFOFAST))
1065 1065                  return;
1066 1066  #if FIFODEBUG
1067 1067          if (Fifo_verbose)
1068 1068                  cmn_err(CE_NOTE, "Fifo reverting to streams mode\n");
1069 1069  #endif
1070 1070  
1071 1071          fifo_fastturnoff(fnp);
1072 1072          if (fnp->fn_flag & ISPIPE) {
1073 1073                  fifo_fastturnoff(fnp->fn_dest);
1074 1074          }
1075 1075  }
1076 1076  
1077 1077  
1078 1078  /*
1079 1079   * flk_lock must be held while calling fifo_fastturnoff() to
1080 1080   * preserve data ordering (no reads or writes allowed)
1081 1081   */
1082 1082  
1083 1083  static void
1084 1084  fifo_fastturnoff(fifonode_t *fnp)
1085 1085  {
1086 1086          fifonode_t *fn_dest = fnp->fn_dest;
1087 1087          mblk_t  *fn_mp;
1088 1088          int     fn_flag;
1089 1089  
1090 1090          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
1091 1091          /*
1092 1092           * Note: This end can't be closed if there
1093 1093           * is stuff in fn_mp
1094 1094           */
1095 1095          if ((fn_mp = fnp->fn_mp) != NULL) {
1096 1096                  ASSERT(fnp->fn_flag & FIFOISOPEN);
1097 1097                  ASSERT(FTOV(fnp)->v_stream != NULL);
1098 1098                  ASSERT(FTOV(fnp)->v_stream->sd_wrq != NULL);
1099 1099                  ASSERT(RD(FTOV(fnp)->v_stream->sd_wrq) != NULL);
1100 1100                  ASSERT(strvp2wq(FTOV(fnp)) != NULL);
1101 1101                  fnp->fn_mp = NULL;
1102 1102                  fnp->fn_count = 0;
1103 1103                  /*
1104 1104                   * Don't need to drop flk_lock across the put()
1105 1105                   * since we're just moving the message from the fifo
1106 1106                   * node to the STREAM head...
1107 1107                   */
1108 1108                  put(RD(strvp2wq(FTOV(fnp))), fn_mp);
1109 1109          }
1110 1110  
1111 1111          /*
1112 1112           * Need to re-issue any pending poll requests
1113 1113           * so that the STREAMS framework sees them
1114 1114           * Writers would be waiting on fnp and readers on fn_dest
1115 1115           */
1116 1116          if ((fnp->fn_flag & (FIFOISOPEN | FIFOPOLLW)) ==
1117 1117              (FIFOISOPEN | FIFOPOLLW)) {
1118 1118                  strpollwakeup(FTOV(fnp), POLLWRNORM);
1119 1119          }
1120 1120          fn_flag = fn_dest->fn_flag;
1121 1121          if ((fn_flag & FIFOISOPEN) == FIFOISOPEN) {
1122 1122                  if ((fn_flag & (FIFOPOLLR | FIFOPOLLRBAND))) {
1123 1123                          strpollwakeup(FTOV(fn_dest), POLLIN|POLLRDNORM);
1124 1124                  }
1125 1125          }
1126 1126          /*
1127 1127           * wake up any sleeping processes so they can notice we went
1128 1128           * to streams mode
1129 1129           */
1130 1130          fnp->fn_flag &= ~(FIFOFAST|FIFOWANTW|FIFOWANTR);
1131 1131          cv_broadcast(&fnp->fn_wait_cv);
1132 1132  }
1133 1133  
1134 1134  /*
1135 1135   * Alternative version of fifo_fastoff()
1136 1136   * optimized for putmsg/getmsg.
1137 1137   */
1138 1138  void
1139 1139  fifo_vfastoff(vnode_t *vp)
1140 1140  {
1141 1141          fifonode_t      *fnp = VTOF(vp);
1142 1142  
1143 1143          mutex_enter(&fnp->fn_lock->flk_lock);
1144 1144          if (!(fnp->fn_flag & FIFOFAST)) {
1145 1145                  mutex_exit(&fnp->fn_lock->flk_lock);
1146 1146                  return;
1147 1147          }
1148 1148          fifo_fastoff(fnp);
1149 1149          mutex_exit(&fnp->fn_lock->flk_lock);
1150 1150  }
1151 1151  
1152 1152  /*
1153 1153   * Wake any sleeping writers, poll and send signals if necessary
1154 1154   * This module is only called when we drop below the hi water mark
1155 1155   * FIFOWANTW indicates that a process is sleeping in fifo_write()
1156 1156   * FIFOHIWATW indicates that we have either attempted a poll or
1157 1157   * non-blocking write and were over the high water mark
1158 1158   * This routine assumes a low water mark of 0.
1159 1159   */
1160 1160  
1161 1161  void
1162 1162  fifo_wakewriter(fifonode_t *fn_dest, fifolock_t *fn_lock)
1163 1163  {
1164 1164          int fn_dflag = fn_dest->fn_flag;
1165 1165  
1166 1166          ASSERT(MUTEX_HELD(&fn_lock->flk_lock));
1167 1167          ASSERT(fn_dest->fn_dest->fn_count < Fifohiwat);
1168 1168          if ((fn_dflag & FIFOWANTW)) {
1169 1169                  cv_broadcast(&fn_dest->fn_wait_cv);
1170 1170          }
1171 1171          if ((fn_dflag & (FIFOHIWATW | FIFOISOPEN)) ==
1172 1172              (FIFOHIWATW | FIFOISOPEN)) {
1173 1173                  if (fn_dflag & FIFOPOLLW)
1174 1174                          strpollwakeup(FTOV(fn_dest), POLLWRNORM);
1175 1175                  if (fn_dflag & FIFOSETSIG)
1176 1176                          str_sendsig(FTOV(fn_dest), S_WRNORM, 0, 0);
1177 1177          }
1178 1178          /*
1179 1179           * FIFOPOLLW can't be set without setting FIFOHIWAT
1180 1180           * This allows us to clear both here.
1181 1181           */
1182 1182          fn_dest->fn_flag = fn_dflag & ~(FIFOWANTW | FIFOHIWATW | FIFOPOLLW);
1183 1183  }
1184 1184  
1185 1185  /*
1186 1186   * wake up any sleeping readers, poll or send signal if needed
1187 1187   * FIFOWANTR indicates that a process is waiting in fifo_read() for data
1188 1188   * FIFOSETSIG indicates that SIGPOLL should be sent to process
1189 1189   * FIFOPOLLR indicates that a poll request for reading on the fifo was made
1190 1190   */
1191 1191  
1192 1192  void
1193 1193  fifo_wakereader(fifonode_t *fn_dest, fifolock_t *fn_lock)
1194 1194  {
1195 1195          int fn_dflag = fn_dest->fn_flag;
1196 1196  
1197 1197          ASSERT(MUTEX_HELD(&fn_lock->flk_lock));
1198 1198          if (fn_dflag & FIFOWANTR) {
1199 1199                  cv_broadcast(&fn_dest->fn_wait_cv);
1200 1200          }
1201 1201          if (fn_dflag & FIFOISOPEN) {
1202 1202                  if (fn_dflag & FIFOPOLLR)
1203 1203                          strpollwakeup(FTOV(fn_dest), POLLIN | POLLRDNORM);
1204 1204                  if (fn_dflag & FIFOSETSIG)
1205 1205                          str_sendsig(FTOV(fn_dest), S_INPUT | S_RDNORM, 0, 0);
1206 1206          }
1207 1207          fn_dest->fn_flag = fn_dflag & ~(FIFOWANTR | FIFOPOLLR);
1208 1208  }
  
    | 
      ↓ open down ↓ | 
    1208 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX