Print this page
    
6474 getupeercred causes spurious event port wakeups on FIFOs
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/fifofs/fifovnops.c
          +++ new/usr/src/uts/common/fs/fifofs/fifovnops.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.
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
  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      -/*        All rights reserved.          */
       22 +/*        All rights reserved.          */
  23   23  
  24   24  
  25   25  /*
  26   26   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  27   27   * Use is subject to license terms.
  28   28   */
  29   29  
  30   30  /*
  31   31   * Copyright 2015, Joyent, Inc.
  32   32   * Copyright (c) 2017 by Delphix. All rights reserved.
  33   33   */
  34   34  
  35   35  /*
  36   36   * FIFOFS file system vnode operations.  This file system
  37   37   * type supports STREAMS-based pipes and FIFOs.
  38   38   */
  39   39  #include <sys/types.h>
  40   40  #include <sys/param.h>
  41   41  #include <sys/systm.h>
  42   42  #include <sys/sysmacros.h>
  43   43  #include <sys/cred.h>
  44   44  #include <sys/errno.h>
  45   45  #include <sys/time.h>
  46   46  #include <sys/file.h>
  47   47  #include <sys/fcntl.h>
  48   48  #include <sys/kmem.h>
  49   49  #include <sys/uio.h>
  50   50  #include <sys/vfs.h>
  51   51  #include <sys/vnode.h>
  52   52  #include <sys/vfs_opreg.h>
  53   53  #include <sys/pathname.h>
  54   54  #include <sys/signal.h>
  55   55  #include <sys/user.h>
  56   56  #include <sys/strsubr.h>
  57   57  #include <sys/stream.h>
  58   58  #include <sys/strsun.h>
  59   59  #include <sys/strredir.h>
  60   60  #include <sys/fs/fifonode.h>
  61   61  #include <sys/fs/namenode.h>
  62   62  #include <sys/stropts.h>
  63   63  #include <sys/proc.h>
  64   64  #include <sys/unistd.h>
  65   65  #include <sys/debug.h>
  66   66  #include <fs/fs_subr.h>
  67   67  #include <sys/filio.h>
  68   68  #include <sys/termio.h>
  69   69  #include <sys/ddi.h>
  70   70  #include <sys/vtrace.h>
  71   71  #include <sys/policy.h>
  72   72  #include <sys/tsol/label.h>
  73   73  
  74   74  /*
  75   75   * Define the routines/data structures used in this file.
  76   76   */
  77   77  static int fifo_read(vnode_t *, uio_t *, int, cred_t *, caller_context_t *);
  78   78  static int fifo_write(vnode_t *, uio_t *, int, cred_t *, caller_context_t *);
  79   79  static int fifo_getattr(vnode_t *, vattr_t *, int, cred_t *,
  80   80          caller_context_t *);
  81   81  static int fifo_setattr(vnode_t *, vattr_t *, int, cred_t *,
  82   82          caller_context_t *);
  83   83  static int fifo_realvp(vnode_t *, vnode_t **, caller_context_t *);
  84   84  static int fifo_access(vnode_t *, int, int, cred_t *, caller_context_t *);
  85   85  static int fifo_create(struct vnode *, char *, vattr_t *, enum vcexcl,
  86   86      int, struct vnode **, struct cred *, int, caller_context_t *,
  87   87      vsecattr_t *);
  88   88  static int fifo_fid(vnode_t *, fid_t *, caller_context_t *);
  89   89  static int fifo_fsync(vnode_t *, int, cred_t *, caller_context_t *);
  90   90  static int fifo_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
  91   91  static int fifo_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
  92   92          caller_context_t *);
  93   93  static int fifo_fastioctl(vnode_t *, int, intptr_t, int, cred_t *, int *);
  94   94  static int fifo_strioctl(vnode_t *, int, intptr_t, int, cred_t *, int *);
  95   95  static int fifo_poll(vnode_t *, short, int, short *, pollhead_t **,
  96   96          caller_context_t *);
  97   97  static int fifo_pathconf(vnode_t *, int, ulong_t *, cred_t *,
  98   98          caller_context_t *);
  99   99  static void fifo_inactive(vnode_t *, cred_t *, caller_context_t *);
 100  100  static int fifo_rwlock(vnode_t *, int, caller_context_t *);
 101  101  static void fifo_rwunlock(vnode_t *, int, caller_context_t *);
 102  102  static int fifo_setsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
 103  103          caller_context_t *);
 104  104  static int fifo_getsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
 105  105          caller_context_t *);
 106  106  
 107  107  /* functions local to this file */
 108  108  static boolean_t fifo_stayfast_enter(fifonode_t *);
 109  109  static void fifo_stayfast_exit(fifonode_t *);
 110  110  
 111  111  /*
 112  112   * Define the data structures external to this file.
 113  113   */
 114  114  extern  dev_t   fifodev;
 115  115  extern struct qinit fifo_stwdata;
 116  116  extern struct qinit fifo_strdata;
 117  117  extern kmutex_t ftable_lock;
 118  118  
 119  119  struct  streamtab fifoinfo = { &fifo_strdata, &fifo_stwdata, NULL, NULL };
 120  120  
 121  121  struct vnodeops *fifo_vnodeops;
 122  122  
 123  123  const fs_operation_def_t fifo_vnodeops_template[] = {
 124  124          VOPNAME_OPEN,           { .vop_open = fifo_open },
 125  125          VOPNAME_CLOSE,          { .vop_close = fifo_close },
 126  126          VOPNAME_READ,           { .vop_read = fifo_read },
 127  127          VOPNAME_WRITE,          { .vop_write = fifo_write },
 128  128          VOPNAME_IOCTL,          { .vop_ioctl = fifo_ioctl },
 129  129          VOPNAME_GETATTR,        { .vop_getattr = fifo_getattr },
 130  130          VOPNAME_SETATTR,        { .vop_setattr = fifo_setattr },
 131  131          VOPNAME_ACCESS,         { .vop_access = fifo_access },
 132  132          VOPNAME_CREATE,         { .vop_create = fifo_create },
 133  133          VOPNAME_FSYNC,          { .vop_fsync = fifo_fsync },
 134  134          VOPNAME_INACTIVE,       { .vop_inactive = fifo_inactive },
 135  135          VOPNAME_FID,            { .vop_fid = fifo_fid },
 136  136          VOPNAME_RWLOCK,         { .vop_rwlock = fifo_rwlock },
 137  137          VOPNAME_RWUNLOCK,       { .vop_rwunlock = fifo_rwunlock },
 138  138          VOPNAME_SEEK,           { .vop_seek = fifo_seek },
 139  139          VOPNAME_REALVP,         { .vop_realvp = fifo_realvp },
 140  140          VOPNAME_POLL,           { .vop_poll = fifo_poll },
 141  141          VOPNAME_PATHCONF,       { .vop_pathconf = fifo_pathconf },
 142  142          VOPNAME_DISPOSE,        { .error = fs_error },
 143  143          VOPNAME_SETSECATTR,     { .vop_setsecattr = fifo_setsecattr },
 144  144          VOPNAME_GETSECATTR,     { .vop_getsecattr = fifo_getsecattr },
 145  145          NULL,                   NULL
 146  146  };
 147  147  
 148  148  /*
 149  149   * Return the fifoinfo structure.
 150  150   */
 151  151  struct streamtab *
 152  152  fifo_getinfo()
 153  153  {
 154  154          return (&fifoinfo);
 155  155  }
 156  156  
 157  157  /*
 158  158   * Trusted Extensions enforces a restrictive policy for
 159  159   * writing via cross-zone named pipes. A privileged global
 160  160   * zone process may expose a named pipe by loopback mounting
 161  161   * it from a lower-level zone to a higher-level zone. The
 162  162   * kernel-enforced mount policy for lofs mounts ensures
 163  163   * that such mounts are read-only in the higher-level
 164  164   * zone. But this is not sufficient to prevent writing
 165  165   * down via fifos.  This function prevents writing down
 166  166   * by comparing the zone of the process which is requesting
 167  167   * write access with the zone owning the named pipe rendezvous.
 168  168   * For write access the zone of the named pipe must equal the
 169  169   * zone of the writing process. Writing up is possible since
 170  170   * the named pipe can be opened for read by a process in a
 171  171   * higher level zone.
 172  172   *
 173  173   * An exception is made for the global zone to support trusted
 174  174   * processes which enforce their own data flow policies.
 175  175   */
 176  176  static boolean_t
 177  177  tsol_fifo_access(vnode_t *vp, int flag, cred_t *crp)
 178  178  {
 179  179          fifonode_t      *fnp = VTOF(vp);
 180  180  
 181  181          if (is_system_labeled() &&
 182  182              (flag & FWRITE) &&
 183  183              (!(fnp->fn_flag & ISPIPE))) {
 184  184                  zone_t  *proc_zone;
 185  185  
 186  186                  proc_zone = crgetzone(crp);
 187  187                  if (proc_zone != global_zone) {
 188  188                          char            vpath[MAXPATHLEN];
 189  189                          zone_t          *fifo_zone;
 190  190  
 191  191                          /*
 192  192                           * Get the pathname and use it to find
 193  193                           * the zone of the fifo.
 194  194                           */
 195  195                          if (vnodetopath(rootdir, vp, vpath, sizeof (vpath),
 196  196                              kcred) == 0) {
 197  197                                  fifo_zone = zone_find_by_path(vpath);
 198  198                                  zone_rele(fifo_zone);
 199  199  
 200  200                                  if (fifo_zone != global_zone &&
 201  201                                      fifo_zone != proc_zone) {
 202  202                                          return (B_FALSE);
 203  203                                  }
 204  204                          } else {
 205  205                                  return (B_FALSE);
 206  206                          }
 207  207                  }
 208  208          }
 209  209          return (B_TRUE);
 210  210  }
 211  211  
 212  212  /*
 213  213   * Open and stream a FIFO.
 214  214   * If this is the first open of the file (FIFO is not streaming),
 215  215   * initialize the fifonode and attach a stream to the vnode.
 216  216   *
 217  217   * Each end of a fifo must be synchronized with the other end.
 218  218   * If not, the mated end may complete an open, I/O, close sequence
 219  219   * before the end waiting in open ever wakes up.
 220  220   * Note: namefs pipes come through this routine too.
 221  221   */
 222  222  int
 223  223  fifo_open(vnode_t **vpp, int flag, cred_t *crp, caller_context_t *ct)
 224  224  {
 225  225          vnode_t         *vp             = *vpp;
 226  226          fifonode_t      *fnp            = VTOF(vp);
 227  227          fifolock_t      *fn_lock        = fnp->fn_lock;
 228  228          int             error;
 229  229  
 230  230          ASSERT(vp->v_type == VFIFO);
 231  231          ASSERT(vn_matchops(vp, fifo_vnodeops));
 232  232  
 233  233          if (!tsol_fifo_access(vp, flag, crp))
 234  234                  return (EACCES);
 235  235  
 236  236          mutex_enter(&fn_lock->flk_lock);
 237  237          /*
 238  238           * If we are the first reader, wake up any writers that
 239  239           * may be waiting around.  wait for all of them to
 240  240           * wake up before proceeding (i.e. fn_wsynccnt == 0)
 241  241           */
 242  242          if (flag & FREAD) {
 243  243                  fnp->fn_rcnt++;         /* record reader present */
 244  244                  if (! (fnp->fn_flag & ISPIPE))
 245  245                          fnp->fn_rsynccnt++;     /* record reader in open */
 246  246          }
 247  247  
 248  248          /*
 249  249           * If we are the first writer, wake up any readers that
 250  250           * may be waiting around.  wait for all of them to
 251  251           * wake up before proceeding (i.e. fn_rsynccnt == 0)
 252  252           */
 253  253          if (flag & FWRITE) {
 254  254                  fnp->fn_wcnt++;         /* record writer present */
 255  255                  if (! (fnp->fn_flag & ISPIPE))
 256  256                          fnp->fn_wsynccnt++;     /* record writer in open */
 257  257          }
 258  258          /*
 259  259           * fifo_stropen will take care of twisting the queues on the first
 260  260           * open.  The 1 being passed in means twist the queues on the first
 261  261           * open.
 262  262           */
 263  263          error = fifo_stropen(vpp, flag, crp, 1, 1);
 264  264          /*
 265  265           * fifo_stropen() could have replaced vpp
 266  266           * since fifo's are the only thing we need to sync up,
 267  267           * everything else just returns;
 268  268           * Note: don't need to hold lock since ISPIPE can't change
 269  269           * and both old and new vp need to be pipes
 270  270           */
 271  271          ASSERT(MUTEX_HELD(&VTOF(*vpp)->fn_lock->flk_lock));
 272  272          if (fnp->fn_flag & ISPIPE) {
 273  273                  ASSERT(VTOF(*vpp)->fn_flag & ISPIPE);
 274  274                  ASSERT(VTOF(*vpp)->fn_rsynccnt == 0);
 275  275                  ASSERT(VTOF(*vpp)->fn_rsynccnt == 0);
 276  276                  /*
 277  277                   * XXX note: should probably hold locks, but
 278  278                   * These values should not be changing
 279  279                   */
 280  280                  ASSERT(fnp->fn_rsynccnt == 0);
 281  281                  ASSERT(fnp->fn_wsynccnt == 0);
 282  282                  mutex_exit(&VTOF(*vpp)->fn_lock->flk_lock);
 283  283                  return (error);
 284  284          }
 285  285          /*
 286  286           * vp can't change for FIFOS
 287  287           */
 288  288          ASSERT(vp == *vpp);
 289  289          /*
 290  290           * If we are opening for read (or writer)
 291  291           *   indicate that the reader (or writer) is done with open
 292  292           *   if there is a writer (or reader) waiting for us, wake them up
 293  293           *      and indicate that at least 1 read (or write) open has occurred
 294  294           *      this is need in the event the read (or write) side closes
 295  295           *      before the writer (or reader) has a chance to wake up
 296  296           *      i.e. it sees that a reader (or writer) was once there
 297  297           */
 298  298          if (flag & FREAD) {
 299  299                  fnp->fn_rsynccnt--;     /* reader done with open */
 300  300                  if (fnp->fn_flag & FIFOSYNC) {
 301  301                          /*
 302  302                           * This indicates that a read open has occurred
 303  303                           * Only need to set if writer is actually asleep
 304  304                           * Flag will be consumed by writer.
 305  305                           */
 306  306                          fnp->fn_flag |= FIFOROCR;
 307  307                          cv_broadcast(&fnp->fn_wait_cv);
 308  308                  }
 309  309          }
 310  310          if (flag & FWRITE) {
 311  311                  fnp->fn_wsynccnt--;     /* writer done with open */
 312  312                  if (fnp->fn_flag & FIFOSYNC) {
 313  313                          /*
 314  314                           * This indicates that a write open has occurred
 315  315                           * Only need to set if reader is actually asleep
 316  316                           * Flag will be consumed by reader.
 317  317                           */
 318  318                          fnp->fn_flag |= FIFOWOCR;
 319  319                          cv_broadcast(&fnp->fn_wait_cv);
 320  320                  }
 321  321          }
 322  322  
 323  323          fnp->fn_flag &= ~FIFOSYNC;
 324  324  
 325  325          /*
 326  326           * errors don't wait around.. just return
 327  327           * Note: XXX other end will wake up and continue despite error.
 328  328           * There is no defined semantic on the correct course of option
 329  329           * so we do what we've done in the past
 330  330           */
 331  331          if (error != 0) {
 332  332                  mutex_exit(&fnp->fn_lock->flk_lock);
 333  333                  goto done;
 334  334          }
 335  335          ASSERT(fnp->fn_rsynccnt <= fnp->fn_rcnt);
 336  336          ASSERT(fnp->fn_wsynccnt <= fnp->fn_wcnt);
 337  337          /*
 338  338           * FIFOWOCR (or FIFOROCR) indicates that the writer (or reader)
 339  339           * has woken us up and is done with open (this way, if the other
 340  340           * end has made it to close, we don't block forever in open)
 341  341           * fn_wnct == fn_wsynccnt (or fn_rcnt == fn_rsynccnt) indicates
 342  342           * that no writer (or reader) has yet made it through open
 343  343           * This has the side benefit of that the first
 344  344           * reader (or writer) will wait until the other end finishes open
 345  345           */
 346  346          if (flag & FREAD) {
 347  347                  while ((fnp->fn_flag & FIFOWOCR) == 0 &&
 348  348                      fnp->fn_wcnt == fnp->fn_wsynccnt) {
 349  349                          if (flag & (FNDELAY|FNONBLOCK)) {
 350  350                                  mutex_exit(&fnp->fn_lock->flk_lock);
 351  351                                  goto done;
 352  352                          }
 353  353                          fnp->fn_insync++;
 354  354                          fnp->fn_flag |= FIFOSYNC;
 355  355                          if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
 356  356                              &fnp->fn_lock->flk_lock)) {
 357  357                                  /*
 358  358                                   * Last reader to wakeup clear writer
 359  359                                   * Clear both writer and reader open
 360  360                                   * occurred flag incase other end is O_RDWR
 361  361                                   */
 362  362                                  if (--fnp->fn_insync == 0 &&
 363  363                                      fnp->fn_flag & FIFOWOCR) {
 364  364                                          fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
 365  365                                  }
 366  366                                  mutex_exit(&fnp->fn_lock->flk_lock);
 367  367                                  (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
 368  368                                  error = EINTR;
 369  369                                  goto done;
 370  370                          }
 371  371                          /*
 372  372                           * Last reader to wakeup clear writer open occurred flag
 373  373                           * Clear both writer and reader open occurred flag
 374  374                           * incase other end is O_RDWR
 375  375                           */
 376  376                          if (--fnp->fn_insync == 0 &&
 377  377                              fnp->fn_flag & FIFOWOCR) {
 378  378                                  fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
 379  379                                  break;
 380  380                          }
 381  381                  }
 382  382          } else if (flag & FWRITE) {
 383  383                  while ((fnp->fn_flag & FIFOROCR) == 0 &&
 384  384                      fnp->fn_rcnt == fnp->fn_rsynccnt) {
 385  385                          if ((flag & (FNDELAY|FNONBLOCK)) && fnp->fn_rcnt == 0) {
 386  386                                  mutex_exit(&fnp->fn_lock->flk_lock);
 387  387                                  (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
 388  388                                  error = ENXIO;
 389  389                                  goto done;
 390  390                          }
 391  391                          fnp->fn_flag |= FIFOSYNC;
 392  392                          fnp->fn_insync++;
 393  393                          if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
 394  394                              &fnp->fn_lock->flk_lock)) {
 395  395                                  /*
 396  396                                   * Last writer to wakeup clear
 397  397                                   * Clear both writer and reader open
 398  398                                   * occurred flag in case other end is O_RDWR
 399  399                                   */
 400  400                                  if (--fnp->fn_insync == 0 &&
 401  401                                      (fnp->fn_flag & FIFOROCR) != 0) {
 402  402                                          fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
 403  403                                  }
 404  404                                  mutex_exit(&fnp->fn_lock->flk_lock);
 405  405                                  (void) fifo_close(*vpp, flag, 1, 0, crp, ct);
 406  406                                  error = EINTR;
 407  407                                  goto done;
 408  408                          }
 409  409                          /*
 410  410                           * Last writer to wakeup clear reader open occurred flag
 411  411                           * Clear both writer and reader open
 412  412                           * occurred flag in case other end is O_RDWR
 413  413                           */
 414  414                          if (--fnp->fn_insync == 0 &&
 415  415                              (fnp->fn_flag & FIFOROCR) != 0) {
 416  416                                  fnp->fn_flag &= ~(FIFOWOCR|FIFOROCR);
 417  417                                  break;
 418  418                          }
 419  419                  }
 420  420          }
 421  421          mutex_exit(&fn_lock->flk_lock);
 422  422  done:
 423  423          return (error);
 424  424  }
 425  425  
 426  426  /*
 427  427   * Close down a stream.
 428  428   * Call cleanlocks() and strclean() on every close.
 429  429   * For last close send hangup message and force
 430  430   * the other end of a named pipe to be unmounted.
 431  431   * Mount guarantees that the mounted end will only call fifo_close()
 432  432   * with a count of 1 when the unmount occurs.
 433  433   * This routine will close down one end of a pipe or FIFO
 434  434   * and free the stream head via strclose()
 435  435   */
 436  436  /*ARGSUSED*/
 437  437  int
 438  438  fifo_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *crp,
 439  439      caller_context_t *ct)
 440  440  {
 441  441          fifonode_t      *fnp            = VTOF(vp);
 442  442          fifonode_t      *fn_dest        = fnp->fn_dest;
 443  443          int             error           = 0;
 444  444          fifolock_t      *fn_lock        = fnp->fn_lock;
 445  445          queue_t         *sd_wrq;
 446  446          vnode_t         *fn_dest_vp;
 447  447          int             senthang = 0;
 448  448  
 449  449          ASSERT(vp->v_stream != NULL);
 450  450          /*
 451  451           * clean locks and clear events.
 452  452           */
 453  453          (void) cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
 454  454          cleanshares(vp, ttoproc(curthread)->p_pid);
 455  455          strclean(vp);
 456  456  
 457  457          /*
 458  458           * If a file still has the pipe/FIFO open, return.
 459  459           */
 460  460          if (count > 1)
 461  461                  return (0);
 462  462  
 463  463  
 464  464          sd_wrq = strvp2wq(vp);
 465  465          mutex_enter(&fn_lock->flk_lock);
 466  466  
 467  467          /*
 468  468           * wait for pending opens to finish up
 469  469           * note: this also has the side effect of single threading closes
 470  470           */
 471  471          while (fn_lock->flk_ocsync)
 472  472                  cv_wait(&fn_lock->flk_wait_cv, &fn_lock->flk_lock);
 473  473  
 474  474          fn_lock->flk_ocsync = 1;
 475  475  
 476  476          if (flag & FREAD) {
 477  477                  fnp->fn_rcnt--;
 478  478          }
 479  479          /*
 480  480           * If we are last writer wake up sleeping readers
 481  481           * (They'll figure out that there are no more writers
 482  482           * and do the right thing)
 483  483           * send hangup down stream so that stream head will do the
 484  484           * right thing.
 485  485           */
 486  486          if (flag & FWRITE) {
 487  487                  if (--fnp->fn_wcnt == 0 && fn_dest->fn_rcnt > 0) {
 488  488                          if ((fn_dest->fn_flag & (FIFOFAST | FIFOWANTR)) ==
 489  489                              (FIFOFAST | FIFOWANTR)) {
 490  490                                  /*
 491  491                                   * While we're at it, clear FIFOWANTW too
 492  492                                   * Wake up any sleeping readers or
 493  493                                   * writers.
 494  494                                   */
 495  495                                  fn_dest->fn_flag &= ~(FIFOWANTR | FIFOWANTW);
 496  496                                  cv_broadcast(&fn_dest->fn_wait_cv);
 497  497                          }
 498  498                          /*
 499  499                           * This is needed incase the other side
 500  500                           * was opened non-blocking.  It is the
 501  501                           * only way we can tell that wcnt is 0 because
 502  502                           * of close instead of never having a writer
 503  503                           */
 504  504                          if (!(fnp->fn_flag & ISPIPE))
 505  505                                  fnp->fn_flag |= FIFOCLOSE;
 506  506                          /*
 507  507                           * Note: sending hangup effectively shuts down
 508  508                           * both reader and writer at other end.
 509  509                           */
 510  510                          (void) putnextctl_wait(sd_wrq, M_HANGUP);
 511  511                          senthang = 1;
 512  512                  }
 513  513          }
 514  514  
 515  515          /*
 516  516           * For FIFOs we need to indicate to stream head that last reader
 517  517           * has gone away so that an error is generated
 518  518           * Pipes just need to wake up the other end so that it can
 519  519           * notice this end has gone away.
 520  520           */
 521  521  
 522  522          if (fnp->fn_rcnt == 0 && fn_dest->fn_wcnt > 0) {
 523  523                  if ((fn_dest->fn_flag & (FIFOFAST | FIFOWANTW)) ==
 524  524                      (FIFOFAST | FIFOWANTW)) {
 525  525                          /*
 526  526                           * wake up any sleeping writers
 527  527                           */
 528  528                          fn_dest->fn_flag &= ~FIFOWANTW;
 529  529                          cv_broadcast(&fn_dest->fn_wait_cv);
 530  530                  }
 531  531          }
 532  532  
 533  533          /*
 534  534           * if there are still processes with this FIFO open
 535  535           *      clear open/close sync flag
 536  536           *      and just return;
 537  537           */
 538  538          if (--fnp->fn_open > 0) {
 539  539                  ASSERT((fnp->fn_rcnt + fnp->fn_wcnt) != 0);
 540  540                  fn_lock->flk_ocsync = 0;
 541  541                  cv_broadcast(&fn_lock->flk_wait_cv);
 542  542                  mutex_exit(&fn_lock->flk_lock);
 543  543                  return (0);
 544  544          }
 545  545  
 546  546          /*
 547  547           * Need to send HANGUP if other side is still open
 548  548           * (fnp->fn_rcnt or fnp->fn_wcnt may not be zero (some thread
 549  549           * on this end of the pipe may still be in fifo_open())
 550  550           *
 551  551           * Note: we can get here with fn_rcnt and fn_wcnt != 0 if some
 552  552           * thread is blocked somewhere in the fifo_open() path prior to
 553  553           * fifo_stropen() incrementing fn_open.  This can occur for
 554  554           * normal FIFOs as well as named pipes.  fn_rcnt and
 555  555           * fn_wcnt only indicate attempts to open. fn_open indicates
 556  556           * successful opens. Partially opened FIFOs should proceed
 557  557           * normally; i.e. they will appear to be new opens.  Partially
  
    | 
      ↓ open down ↓ | 
    525 lines elided | 
    
      ↑ open up ↑ | 
  
 558  558           * opened pipes will probably fail.
 559  559           */
 560  560  
 561  561          if (fn_dest->fn_open && senthang == 0)
 562  562                  (void) putnextctl_wait(sd_wrq, M_HANGUP);
 563  563  
 564  564  
 565  565          /*
 566  566           * If this a pipe and this is the first end to close,
 567  567           * then we have a bit of cleanup work to do.
 568      -         *      Mark both ends of pipe as closed.
 569      -         *      Wake up anybody blocked at the other end and for named pipes,
      568 +         *      Mark both ends of pipe as closed.
      569 +         *      Wake up anybody blocked at the other end and for named pipes,
 570  570           *      Close down this end of the stream
 571  571           *      Allow other opens/closes to continue
 572      -         *      force an unmount of other end.
      572 +         *      force an unmount of other end.
 573  573           * Otherwise if this is last close,
 574  574           *      flush messages,
 575  575           *      close down the stream
 576  576           *      allow other opens/closes to continue
 577  577           */
 578  578          fnp->fn_flag &= ~FIFOISOPEN;
 579  579          if ((fnp->fn_flag & ISPIPE) && !(fnp->fn_flag & FIFOCLOSE)) {
 580  580                  fnp->fn_flag |= FIFOCLOSE;
 581  581                  fn_dest->fn_flag |= FIFOCLOSE;
 582  582                  if (fnp->fn_flag & FIFOFAST)
 583  583                          fifo_fastflush(fnp);
 584  584                  if (vp->v_stream != NULL) {
 585  585                          mutex_exit(&fn_lock->flk_lock);
 586  586                          (void) strclose(vp, flag, crp);
 587  587                          mutex_enter(&fn_lock->flk_lock);
 588  588                  }
 589  589                  cv_broadcast(&fn_dest->fn_wait_cv);
 590  590                  /*
 591  591                   * allow opens and closes to proceed
 592  592                   * Since this end is now closed down, any attempt
 593  593                   * to do anything with this end will fail
 594  594                   */
 595  595                  fn_lock->flk_ocsync = 0;
 596  596                  cv_broadcast(&fn_lock->flk_wait_cv);
 597  597                  fn_dest_vp = FTOV(fn_dest);
 598  598                  /*
 599  599                   * if other end of pipe has been opened and it's
 600  600                   * a named pipe, unmount it
 601  601                   */
 602  602                  if (fn_dest_vp->v_stream &&
 603  603                      (fn_dest_vp->v_stream->sd_flag & STRMOUNT)) {
 604  604                          /*
 605  605                           * We must hold the destination vnode because
 606  606                           * nm_unmountall() causes close to be called
 607  607                           * for the other end of named pipe.  This
 608  608                           * could free the vnode before we are ready.
 609  609                           */
 610  610                          VN_HOLD(fn_dest_vp);
 611  611                          mutex_exit(&fn_lock->flk_lock);
 612  612                          error = nm_unmountall(fn_dest_vp, crp);
 613  613                          ASSERT(error == 0);
 614  614                          VN_RELE(fn_dest_vp);
 615  615                  } else {
 616  616                          ASSERT(vp->v_count >= 1);
 617  617                          mutex_exit(&fn_lock->flk_lock);
 618  618                  }
 619  619          } else {
 620  620                  if (fnp->fn_flag & FIFOFAST)
 621  621                          fifo_fastflush(fnp);
 622  622  #if DEBUG
 623  623                  fn_dest_vp = FTOV(fn_dest);
 624  624                  if (fn_dest_vp->v_stream)
 625  625                          ASSERT((fn_dest_vp->v_stream->sd_flag & STRMOUNT) == 0);
 626  626  #endif
 627  627                  if (vp->v_stream != NULL) {
 628  628                          mutex_exit(&fn_lock->flk_lock);
 629  629                          (void) strclose(vp, flag, crp);
 630  630                          mutex_enter(&fn_lock->flk_lock);
 631  631                  }
 632  632                  fn_lock->flk_ocsync = 0;
 633  633                  cv_broadcast(&fn_lock->flk_wait_cv);
 634  634                  cv_broadcast(&fn_dest->fn_wait_cv);
 635  635                  mutex_exit(&fn_lock->flk_lock);
 636  636          }
 637  637          return (error);
 638  638  }
 639  639  
 640  640  /*
 641  641   * Read from a pipe or FIFO.
 642  642   * return 0 if....
 643  643   *    (1) user read request is 0 or no stream
 644  644   *    (2) broken pipe with no data
 645  645   *    (3) write-only FIFO with no data
 646  646   *    (4) no data and FNDELAY flag is set.
 647  647   * Otherwise return
 648  648   *      EAGAIN if FNONBLOCK is set and no data to read
 649  649   *      EINTR if signal received while waiting for data
 650  650   *
 651  651   * While there is no data to read....
 652  652   *   -  if the NDELAY/NONBLOCK flag is set, return 0/EAGAIN.
 653  653   *   -  wait for a write.
 654  654   *
 655  655   */
 656  656  /*ARGSUSED*/
 657  657  
 658  658  static int
 659  659  fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
 660  660      caller_context_t *ct)
 661  661  {
 662  662          fifonode_t      *fnp            = VTOF(vp);
 663  663          fifonode_t      *fn_dest;
 664  664          fifolock_t      *fn_lock        = fnp->fn_lock;
 665  665          int             error           = 0;
 666  666          mblk_t          *bp;
 667  667  
 668  668          ASSERT(vp->v_stream != NULL);
 669  669          if (uiop->uio_resid == 0)
 670  670                  return (0);
 671  671  
 672  672          mutex_enter(&fn_lock->flk_lock);
 673  673  
 674  674          TRACE_2(TR_FAC_FIFO, TR_FIFOREAD_IN, "fifo_read in:%p fnp %p", vp, fnp);
 675  675  
 676  676          if (! (fnp->fn_flag & FIFOFAST))
 677  677                  goto stream_mode;
 678  678  
 679  679          fn_dest = fnp->fn_dest;
 680  680          /*
 681  681           * Check for data on our input queue
 682  682           */
 683  683  
 684  684          while (fnp->fn_count == 0) {
 685  685                  /*
 686  686                   * No data on first attempt and no writer, then EOF
 687  687                   */
 688  688                  if (fn_dest->fn_wcnt == 0 || fn_dest->fn_rcnt == 0) {
 689  689                          mutex_exit(&fn_lock->flk_lock);
 690  690                          return (0);
 691  691                  }
 692  692                  /*
 693  693                   * no data found.. if non-blocking, return EAGAIN
 694  694                   * otherwise 0.
 695  695                   */
 696  696                  if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
 697  697                          mutex_exit(&fn_lock->flk_lock);
 698  698                          if (uiop->uio_fmode & FNONBLOCK)
 699  699                                  return (EAGAIN);
 700  700                          return (0);
 701  701                  }
 702  702  
 703  703                  /*
 704  704                   * Note: FIFOs can get here with FIFOCLOSE set if
 705  705                   * write side is in the middle of opeining after
 706  706                   * it once closed. Pipes better not have FIFOCLOSE set
 707  707                   */
 708  708                  ASSERT((fnp->fn_flag & (ISPIPE|FIFOCLOSE)) !=
 709  709                      (ISPIPE|FIFOCLOSE));
 710  710                  /*
 711  711                   * wait for data
 712  712                   */
 713  713                  fnp->fn_flag |= FIFOWANTR;
 714  714  
 715  715                  TRACE_1(TR_FAC_FIFO, TR_FIFOREAD_WAIT, "fiforead wait: %p", vp);
 716  716  
 717  717                  if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
 718  718                      &fn_lock->flk_lock)) {
 719  719                          error = EINTR;
 720  720                          goto done;
 721  721                  }
 722  722  
 723  723                  TRACE_1(TR_FAC_FIFO, TR_FIFOREAD_WAKE,
 724  724                      "fiforead awake: %p", vp);
 725  725  
 726  726                  /*
 727  727                   * check to make sure we are still in fast mode
 728  728                   */
 729  729                  if (!(fnp->fn_flag & FIFOFAST))
 730  730                          goto stream_mode;
 731  731          }
 732  732  
 733  733          ASSERT(fnp->fn_mp != NULL);
 734  734  
 735  735          /* For pipes copy should not bypass cache */
 736  736          uiop->uio_extflg |= UIO_COPY_CACHED;
 737  737  
 738  738          do {
 739  739                  int bpsize = MBLKL(fnp->fn_mp);
 740  740                  int uiosize = MIN(bpsize, uiop->uio_resid);
 741  741  
 742  742                  error = uiomove(fnp->fn_mp->b_rptr, uiosize, UIO_READ, uiop);
 743  743                  if (error != 0)
 744  744                          break;
 745  745  
 746  746                  fnp->fn_count -= uiosize;
 747  747  
 748  748                  if (bpsize <= uiosize) {
 749  749                          bp = fnp->fn_mp;
 750  750                          fnp->fn_mp = fnp->fn_mp->b_cont;
 751  751                          freeb(bp);
 752  752  
 753  753                          if (uiop->uio_resid == 0)
 754  754                                  break;
 755  755  
 756  756                          while (fnp->fn_mp == NULL && fn_dest->fn_wwaitcnt > 0) {
 757  757                                  ASSERT(fnp->fn_count == 0);
 758  758  
 759  759                                  if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
 760  760                                          goto trywake;
 761  761  
 762  762                                  /*
 763  763                                   * We've consumed all available data but there
 764  764                                   * are threads waiting to write more, let them
 765  765                                   * proceed before bailing.
 766  766                                   */
 767  767  
 768  768                                  fnp->fn_flag |= FIFOWANTR;
 769  769                                  fifo_wakewriter(fn_dest, fn_lock);
 770  770  
 771  771                                  if (!cv_wait_sig(&fnp->fn_wait_cv,
 772  772                                      &fn_lock->flk_lock))
 773  773                                          goto trywake;
 774  774  
 775  775                                  if (!(fnp->fn_flag & FIFOFAST))
 776  776                                          goto stream_mode;
 777  777                          }
 778  778                  } else {
 779  779                          fnp->fn_mp->b_rptr += uiosize;
 780  780                          ASSERT(uiop->uio_resid == 0);
 781  781                  }
 782  782          } while (uiop->uio_resid != 0 && fnp->fn_mp != NULL);
 783  783  
 784  784  trywake:
 785  785          ASSERT(msgdsize(fnp->fn_mp) == fnp->fn_count);
 786  786  
 787  787          /*
 788  788           * wake up any blocked writers, processes
 789  789           * sleeping on POLLWRNORM, or processes waiting for SIGPOLL
 790  790           * Note: checking for fn_count < Fifohiwat emulates
 791  791           * STREAMS functionality when low water mark is 0
 792  792           */
 793  793          if (fn_dest->fn_flag & (FIFOWANTW | FIFOHIWATW) &&
 794  794              fnp->fn_count < Fifohiwat) {
 795  795                  fifo_wakewriter(fn_dest, fn_lock);
 796  796          }
 797  797          goto done;
 798  798  
 799  799          /*
 800  800           * FIFO is in streams mode.. let the stream head handle it
 801  801           */
 802  802  stream_mode:
 803  803  
 804  804          mutex_exit(&fn_lock->flk_lock);
 805  805          TRACE_1(TR_FAC_FIFO,
 806  806              TR_FIFOREAD_STREAM, "fifo_read stream_mode:%p", vp);
 807  807  
 808  808          error = strread(vp, uiop, crp);
 809  809  
 810  810          mutex_enter(&fn_lock->flk_lock);
 811  811  
 812  812  done:
 813  813          /*
 814  814           * vnode update access time
 815  815           */
 816  816          if (error == 0) {
 817  817                  time_t now = gethrestime_sec();
 818  818  
 819  819                  if (fnp->fn_flag & ISPIPE)
 820  820                          fnp->fn_dest->fn_atime = now;
 821  821                  fnp->fn_atime = now;
 822  822          }
 823  823          TRACE_2(TR_FAC_FIFO, TR_FIFOREAD_OUT,
 824  824              "fifo_read out:%p error %d", vp, error);
 825  825          mutex_exit(&fn_lock->flk_lock);
 826  826          return (error);
 827  827  }
 828  828  
 829  829  /*
 830  830   * send SIGPIPE and return EPIPE if ...
 831  831   *   (1) broken pipe (essentially, reader is gone)
 832  832   *   (2) FIFO is not open for reading
 833  833   * return 0 if...
 834  834   *   (1) no stream
 835  835   *   (2) user write request is for 0 bytes and SW_SNDZERO is not set
 836  836   *      Note: SW_SNDZERO can't be set in fast mode
 837  837   * While the stream is flow controlled....
 838  838   *   -  if the NDELAY/NONBLOCK flag is set, return 0/EAGAIN.
 839  839   *   -  unlock the fifonode and sleep waiting for a reader.
 840  840   *   -  if a pipe and it has a mate, sleep waiting for its mate
 841  841   *      to read.
 842  842   */
 843  843  /*ARGSUSED*/
 844  844  static int
 845  845  fifo_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *crp,
 846  846      caller_context_t *ct)
 847  847  {
 848  848          struct fifonode *fnp, *fn_dest;
 849  849          fifolock_t      *fn_lock;
 850  850          struct stdata   *stp;
 851  851          int             error   = 0;
 852  852          int             write_size;
 853  853          int             size;
 854  854          int             fmode;
 855  855          mblk_t          *bp;
 856  856          boolean_t       hotread;
 857  857  
 858  858          ASSERT(vp->v_stream);
 859  859          uiop->uio_loffset = 0;
 860  860          stp     = vp->v_stream;
 861  861  
 862  862          /*
 863  863           * remember original number of bytes requested. Used to determine if
 864  864           * we actually have written anything at all
 865  865           */
 866  866          write_size = uiop->uio_resid;
 867  867  
 868  868          /*
 869  869           * only send zero-length messages if SW_SNDZERO is set
 870  870           * Note: we will be in streams mode if SW_SNDZERO is set
 871  871           * XXX this streams interface should not be exposed
 872  872           */
 873  873          if ((write_size == 0) && !(stp->sd_wput_opt & SW_SNDZERO))
 874  874                  return (0);
 875  875  
 876  876          fnp = VTOF(vp);
 877  877          fn_lock = fnp->fn_lock;
 878  878          fn_dest = fnp->fn_dest;
 879  879  
 880  880          mutex_enter(&fn_lock->flk_lock);
 881  881  
 882  882          TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_IN,
 883  883              "fifo_write in:%p fnp %p size %d", vp, fnp, write_size);
 884  884  
 885  885          /*
 886  886           * oops, no readers, error
 887  887           */
 888  888          if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
 889  889                  goto epipe;
 890  890          }
 891  891  
 892  892          /*
 893  893           * if we are not in fast mode, let streams handle it
 894  894           */
 895  895          if (!(fnp->fn_flag & FIFOFAST))
 896  896                  goto stream_mode;
 897  897  
 898  898          fmode = uiop->uio_fmode & (FNDELAY|FNONBLOCK);
 899  899  
 900  900          /* For pipes copy should not bypass cache */
 901  901          uiop->uio_extflg |= UIO_COPY_CACHED;
 902  902  
 903  903          do  {
 904  904                  /*
 905  905                   * check to make sure we are not over high water mark
 906  906                   */
 907  907                  while (fn_dest->fn_count >= Fifohiwat) {
 908  908                          /*
 909  909                           * Indicate that we have gone over high
 910  910                           * water mark
 911  911                           */
 912  912                          /*
 913  913                           * if non-blocking, return
 914  914                           * only happens first time through loop
 915  915                           */
 916  916                          if (fmode) {
 917  917                                  fnp->fn_flag |= FIFOHIWATW;
 918  918                                  if (uiop->uio_resid == write_size) {
 919  919                                          mutex_exit(&fn_lock->flk_lock);
 920  920                                          if (fmode & FNDELAY)
 921  921                                                  return (0);
 922  922                                          else
 923  923                                                  return (EAGAIN);
 924  924                                  }
 925  925                                  goto done;
 926  926                          }
 927  927  
 928  928                          /*
 929  929                           * wait for things to drain
 930  930                           */
 931  931                          fnp->fn_flag |= FIFOWANTW;
 932  932                          fnp->fn_wwaitcnt++;
 933  933                          TRACE_1(TR_FAC_FIFO, TR_FIFOWRITE_WAIT,
 934  934                              "fifo_write wait: %p", vp);
 935  935                          if (!cv_wait_sig_swap(&fnp->fn_wait_cv,
 936  936                              &fn_lock->flk_lock)) {
 937  937                                  error = EINTR;
 938  938                                  fnp->fn_wwaitcnt--;
 939  939                                  fifo_wakereader(fn_dest, fn_lock);
 940  940                                  goto done;
 941  941                          }
 942  942                          fnp->fn_wwaitcnt--;
 943  943  
 944  944                          TRACE_1(TR_FAC_FIFO, TR_FIFOWRITE_WAKE,
 945  945                              "fifo_write wake: %p", vp);
 946  946  
 947  947                          /*
 948  948                           * check to make sure we're still in fast mode
 949  949                           */
 950  950                          if (!(fnp->fn_flag & FIFOFAST))
 951  951                                  goto stream_mode;
 952  952  
 953  953                          /*
 954  954                           * make sure readers didn't go away
 955  955                           */
 956  956                          if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
 957  957                                  goto epipe;
 958  958                          }
 959  959                  }
 960  960                  /*
 961  961                   * If the write will put us over the high water mark,
 962  962                   * then we must break the message up into PIPE_BUF
 963  963                   * chunks to stay compliant with STREAMS
 964  964                   */
 965  965                  if (uiop->uio_resid + fn_dest->fn_count > Fifohiwat)
 966  966                          size = MIN(uiop->uio_resid, PIPE_BUF);
 967  967                  else
 968  968                          size = uiop->uio_resid;
 969  969  
 970  970                  /*
 971  971                   * We don't need to hold flk_lock across the allocb() and
 972  972                   * uiomove().  However, on a multiprocessor machine where both
 973  973                   * the reader and writer thread are on cpu's, we must be
 974  974                   * careful to only drop the lock if there's data to be read.
 975  975                   * This forces threads entering fifo_read() to spin or block
 976  976                   * on flk_lock, rather than acquiring flk_lock only to
 977  977                   * discover there's no data to read and being forced to go
 978  978                   * back to sleep, only to be woken up microseconds later by
 979  979                   * this writer thread.
 980  980                   */
 981  981                  hotread = fn_dest->fn_count > 0;
 982  982                  if (hotread) {
 983  983                          if (!fifo_stayfast_enter(fnp))
 984  984                                  goto stream_mode;
 985  985                          mutex_exit(&fn_lock->flk_lock);
 986  986                  }
 987  987  
 988  988                  ASSERT(size != 0);
 989  989                  /*
 990  990                   * Align the mblk with the user data so that
 991  991                   * copying in the data can take advantage of
 992  992                   * the double word alignment
 993  993                   */
 994  994                  if ((bp = allocb(size + 8, BPRI_MED)) == NULL) {
 995  995                          if (!hotread)
 996  996                                  mutex_exit(&fn_lock->flk_lock);
 997  997  
 998  998                          error = strwaitbuf(size, BPRI_MED);
 999  999  
1000 1000                          mutex_enter(&fn_lock->flk_lock);
1001 1001  
1002 1002                          if (hotread) {
1003 1003                                  /*
1004 1004                                   * As we dropped the mutex for a moment, we
1005 1005                                   * need to wake up any thread waiting to be
1006 1006                                   * allowed to go from fast mode to stream mode.
1007 1007                                   */
1008 1008                                  fifo_stayfast_exit(fnp);
1009 1009                          }
1010 1010                          if (error != 0) {
1011 1011                                  goto done;
1012 1012                          }
1013 1013                          /*
1014 1014                           * check to make sure we're still in fast mode
1015 1015                           */
1016 1016                          if (!(fnp->fn_flag & FIFOFAST))
1017 1017                                  goto stream_mode;
1018 1018  
1019 1019                          /*
1020 1020                           * make sure readers didn't go away
1021 1021                           */
1022 1022                          if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1023 1023                                  goto epipe;
1024 1024                          }
1025 1025                          /*
1026 1026                           * some other thread could have gotten in
1027 1027                           * need to go back and check hi water mark
1028 1028                           */
1029 1029                          continue;
1030 1030                  }
1031 1031                  bp->b_rptr += ((uintptr_t)uiop->uio_iov->iov_base & 0x7);
1032 1032                  bp->b_wptr = bp->b_rptr + size;
1033 1033                  error = uiomove((caddr_t)bp->b_rptr, size, UIO_WRITE, uiop);
1034 1034                  if (hotread) {
1035 1035                          mutex_enter(&fn_lock->flk_lock);
1036 1036                          /*
1037 1037                           * As we dropped the mutex for a moment, we need to:
1038 1038                           * - wake up any thread waiting to be allowed to go
1039 1039                           *   from fast mode to stream mode,
1040 1040                           * - make sure readers didn't go away.
1041 1041                           */
1042 1042                          fifo_stayfast_exit(fnp);
1043 1043                          if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1044 1044                                  freeb(bp);
1045 1045                                  goto epipe;
1046 1046                          }
1047 1047                  }
1048 1048  
1049 1049                  if (error != 0) {
1050 1050                          freeb(bp);
1051 1051                          goto done;
1052 1052                  }
1053 1053  
1054 1054                  fn_dest->fn_count += size;
1055 1055                  if (fn_dest->fn_mp != NULL) {
1056 1056                          fn_dest->fn_tail->b_cont = bp;
1057 1057                          fn_dest->fn_tail = bp;
1058 1058                  } else {
1059 1059                          fn_dest->fn_mp = fn_dest->fn_tail = bp;
1060 1060                          /*
1061 1061                           * This is the first bit of data; wake up any sleeping
1062 1062                           * readers, processes blocked in poll, and those
1063 1063                           * expecting a SIGPOLL.
1064 1064                           */
1065 1065                          fifo_wakereader(fn_dest, fn_lock);
1066 1066                  }
1067 1067          } while (uiop->uio_resid != 0);
1068 1068  
1069 1069          goto done;
1070 1070  
1071 1071  stream_mode:
1072 1072          /*
1073 1073           * streams mode
1074 1074           *  let the stream head handle the write
1075 1075           */
1076 1076          ASSERT(MUTEX_HELD(&fn_lock->flk_lock));
1077 1077  
1078 1078          mutex_exit(&fn_lock->flk_lock);
1079 1079          TRACE_1(TR_FAC_FIFO,
1080 1080              TR_FIFOWRITE_STREAM, "fifo_write stream_mode:%p", vp);
1081 1081  
1082 1082          error = strwrite(vp, uiop, crp);
1083 1083  
1084 1084          mutex_enter(&fn_lock->flk_lock);
1085 1085  
1086 1086  done:
1087 1087          /*
1088 1088           * update vnode modification and change times
1089 1089           * make sure there were no errors and some data was transferred
1090 1090           */
1091 1091          if (error == 0 && write_size != uiop->uio_resid) {
1092 1092                  time_t now = gethrestime_sec();
1093 1093  
1094 1094                  if (fnp->fn_flag & ISPIPE) {
1095 1095                          fn_dest->fn_mtime = fn_dest->fn_ctime = now;
1096 1096                  }
1097 1097                  fnp->fn_mtime = fnp->fn_ctime = now;
1098 1098          } else if (fn_dest->fn_rcnt == 0 || fn_dest->fn_wcnt == 0) {
1099 1099                  goto epipe;
1100 1100          }
1101 1101          TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_OUT,
1102 1102              "fifo_write out: vp %p error %d fnp %p", vp, error, fnp);
1103 1103          mutex_exit(&fn_lock->flk_lock);
1104 1104          return (error);
1105 1105  epipe:
1106 1106          error = EPIPE;
1107 1107          TRACE_3(TR_FAC_FIFO, TR_FIFOWRITE_OUT,
1108 1108              "fifo_write out: vp %p error %d fnp %p", vp, error, fnp);
1109 1109          mutex_exit(&fn_lock->flk_lock);
1110 1110          tsignal(curthread, SIGPIPE);
1111 1111          return (error);
1112 1112  }
1113 1113  
1114 1114  /*ARGSUSED6*/
1115 1115  static int
1116 1116  fifo_ioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1117 1117      int *rvalp, caller_context_t *ct)
1118 1118  {
1119 1119          /*
  
    | 
      ↓ open down ↓ | 
    537 lines elided | 
    
      ↑ open up ↑ | 
  
1120 1120           * Just a quick check
1121 1121           * Once we go to streams mode we don't ever revert back
1122 1122           * So we do this quick check so as not to incur the overhead
1123 1123           * associated with acquiring the lock
1124 1124           */
1125 1125          return ((VTOF(vp)->fn_flag & FIFOFAST) ?
1126 1126              fifo_fastioctl(vp, cmd, arg, mode, cr, rvalp) :
1127 1127              fifo_strioctl(vp, cmd, arg, mode, cr, rvalp));
1128 1128  }
1129 1129  
     1130 +static inline int
     1131 +fifo_ioctl_getpeercred(fifonode_t *fnp, intptr_t arg, int mode)
     1132 +{
     1133 +        k_peercred_t *kp = (k_peercred_t *)arg;
     1134 +
     1135 +        if (mode == FKIOCTL && fnp->fn_pcredp != NULL) {
     1136 +                crhold(fnp->fn_pcredp);
     1137 +                kp->pc_cr = fnp->fn_pcredp;
     1138 +                kp->pc_cpid = fnp->fn_cpid;
     1139 +                return (0);
     1140 +        } else {
     1141 +                return (ENOTSUP);
     1142 +        }
     1143 +}
     1144 +
1130 1145  static int
1131 1146  fifo_fastioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1132 1147      int *rvalp)
1133 1148  {
1134 1149          fifonode_t      *fnp            = VTOF(vp);
1135 1150          fifonode_t      *fn_dest;
1136 1151          int             error           = 0;
1137 1152          fifolock_t      *fn_lock        = fnp->fn_lock;
1138 1153          int             cnt;
1139 1154  
1140 1155          /*
1141 1156           * tty operations not allowed
1142 1157           */
1143 1158          if (((cmd & IOCTYPE) == LDIOC) ||
1144 1159              ((cmd & IOCTYPE) == tIOC) ||
1145 1160              ((cmd & IOCTYPE) == TIOC)) {
1146 1161                  return (EINVAL);
1147 1162          }
1148 1163  
1149 1164          mutex_enter(&fn_lock->flk_lock);
1150 1165  
1151 1166          if (!(fnp->fn_flag & FIFOFAST)) {
1152 1167                  goto stream_mode;
1153 1168          }
1154 1169  
1155 1170          switch (cmd) {
1156 1171  
1157 1172          /*
1158 1173           * Things we can't handle
1159 1174           * These will switch us to streams mode.
1160 1175           */
1161 1176          default:
1162 1177          case I_STR:
1163 1178          case I_SRDOPT:
1164 1179          case I_PUSH:
1165 1180          case I_FDINSERT:
1166 1181          case I_SENDFD:
1167 1182          case I_RECVFD:
1168 1183          case I_E_RECVFD:
1169 1184          case I_ATMARK:
1170 1185          case I_CKBAND:
1171 1186          case I_GETBAND:
1172 1187          case I_SWROPT:
1173 1188                  goto turn_fastoff;
1174 1189  
1175 1190          /*
1176 1191           * Things that don't do damage
1177 1192           * These things don't adjust the state of the
1178 1193           * stream head (i_setcltime does, but we don't care)
1179 1194           */
1180 1195          case I_FIND:
1181 1196          case I_GETSIG:
1182 1197          case FIONBIO:
1183 1198          case FIOASYNC:
1184 1199          case I_GRDOPT:  /* probably should not get this, but no harm */
1185 1200          case I_GWROPT:
1186 1201          case I_LIST:
1187 1202          case I_SETCLTIME:
1188 1203          case I_GETCLTIME:
1189 1204                  mutex_exit(&fn_lock->flk_lock);
1190 1205                  return (strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp));
1191 1206  
1192 1207          case I_CANPUT:
1193 1208                  /*
1194 1209                   * We can only handle normal band canputs.
1195 1210                   * XXX : We could just always go to stream mode; after all
1196 1211                   * canput is a streams semantics type thing
1197 1212                   */
1198 1213                  if (arg != 0) {
1199 1214                          goto turn_fastoff;
1200 1215                  }
1201 1216                  *rvalp = (fnp->fn_dest->fn_count < Fifohiwat) ? 1 : 0;
1202 1217                  mutex_exit(&fn_lock->flk_lock);
1203 1218                  return (0);
1204 1219  
1205 1220          case I_NREAD:
1206 1221                  /*
1207 1222                   * This may seem a bit silly for non-streams semantics,
1208 1223                   * (After all, if they really want a message, they'll
1209 1224                   * probably use getmsg() anyway). but it doesn't hurt
1210 1225                   */
1211 1226                  error = copyout((caddr_t)&fnp->fn_count, (caddr_t)arg,
1212 1227                      sizeof (cnt));
1213 1228                  if (error == 0) {
1214 1229                          *rvalp = (fnp->fn_count == 0) ? 0 : 1;
1215 1230                  }
1216 1231                  break;
1217 1232  
1218 1233          case FIORDCHK:
1219 1234                  *rvalp = fnp->fn_count;
1220 1235                  break;
1221 1236  
1222 1237          case I_PEEK:
1223 1238          {
1224 1239                  STRUCT_DECL(strpeek, strpeek);
1225 1240                  struct uio      uio;
1226 1241                  struct iovec    iov;
1227 1242                  int             count;
1228 1243                  mblk_t          *bp;
1229 1244                  int             len;
1230 1245  
1231 1246                  STRUCT_INIT(strpeek, mode);
1232 1247  
1233 1248                  if (fnp->fn_count == 0) {
1234 1249                          *rvalp = 0;
1235 1250                          break;
1236 1251                  }
1237 1252  
1238 1253                  error = copyin((caddr_t)arg, STRUCT_BUF(strpeek),
1239 1254                      STRUCT_SIZE(strpeek));
1240 1255                  if (error)
1241 1256                          break;
1242 1257  
1243 1258                  /*
1244 1259                   * can't have any high priority message when in fast mode
1245 1260                   */
1246 1261                  if (STRUCT_FGET(strpeek, flags) & RS_HIPRI) {
1247 1262                          *rvalp = 0;
1248 1263                          break;
1249 1264                  }
1250 1265  
1251 1266                  len = STRUCT_FGET(strpeek, databuf.maxlen);
1252 1267                  if (len <= 0) {
1253 1268                          STRUCT_FSET(strpeek, databuf.len, len);
1254 1269                  } else {
1255 1270                          iov.iov_base = STRUCT_FGETP(strpeek, databuf.buf);
1256 1271                          iov.iov_len = len;
1257 1272                          uio.uio_iov = &iov;
1258 1273                          uio.uio_iovcnt = 1;
1259 1274                          uio.uio_loffset = 0;
1260 1275                          uio.uio_segflg = UIO_USERSPACE;
1261 1276                          uio.uio_fmode = 0;
1262 1277                          /* For pipes copy should not bypass cache */
1263 1278                          uio.uio_extflg = UIO_COPY_CACHED;
1264 1279                          uio.uio_resid = iov.iov_len;
1265 1280                          count = fnp->fn_count;
1266 1281                          bp = fnp->fn_mp;
1267 1282                          while (count > 0 && uio.uio_resid) {
1268 1283                                  cnt = MIN(uio.uio_resid, MBLKL(bp));
1269 1284                                  if ((error = uiomove((char *)bp->b_rptr, cnt,
1270 1285                                      UIO_READ, &uio)) != 0) {
1271 1286                                          break;
1272 1287                                  }
1273 1288                                  count -= cnt;
1274 1289                                  bp = bp->b_cont;
1275 1290                          }
1276 1291                          STRUCT_FSET(strpeek, databuf.len, len - uio.uio_resid);
1277 1292                  }
1278 1293                  STRUCT_FSET(strpeek, flags, 0);
1279 1294                  STRUCT_FSET(strpeek, ctlbuf.len, -1);
1280 1295  
1281 1296                  error = copyout(STRUCT_BUF(strpeek), (caddr_t)arg,
1282 1297                      STRUCT_SIZE(strpeek));
1283 1298                  if (error == 0 && len >= 0)
1284 1299                          *rvalp = 1;
1285 1300                  break;
1286 1301          }
1287 1302  
1288 1303          case FIONREAD:
1289 1304                  /*
1290 1305                   * let user know total number of bytes in message queue
1291 1306                   */
1292 1307                  error = copyout((caddr_t)&fnp->fn_count, (caddr_t)arg,
1293 1308                      sizeof (fnp->fn_count));
1294 1309                  if (error == 0)
1295 1310                          *rvalp = 0;
1296 1311                  break;
1297 1312  
1298 1313          case I_SETSIG:
1299 1314                  /*
1300 1315                   * let streams set up the signal masking for us
1301 1316                   * we just check to see if it's set
1302 1317                   * XXX : this interface should not be visible
1303 1318                   *  i.e. STREAM's framework is exposed.
1304 1319                   */
1305 1320                  error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp);
1306 1321                  if (vp->v_stream->sd_sigflags & (S_INPUT|S_RDNORM|S_WRNORM))
1307 1322                          fnp->fn_flag |= FIFOSETSIG;
1308 1323                  else
1309 1324                          fnp->fn_flag &= ~FIFOSETSIG;
1310 1325                  break;
1311 1326  
1312 1327          case I_FLUSH:
1313 1328                  /*
1314 1329                   * flush them message queues
1315 1330                   */
1316 1331                  if (arg & ~FLUSHRW) {
1317 1332                          error = EINVAL;
1318 1333                          break;
1319 1334                  }
1320 1335                  if (arg & FLUSHR) {
1321 1336                          fifo_fastflush(fnp);
1322 1337                  }
1323 1338                  fn_dest = fnp->fn_dest;
1324 1339                  if ((arg & FLUSHW)) {
1325 1340                          fifo_fastflush(fn_dest);
1326 1341                  }
1327 1342                  /*
1328 1343                   * wake up any sleeping readers or writers
1329 1344                   * (waking readers probably doesn't make sense, but it
1330 1345                   *  doesn't hurt; i.e. we just got rid of all the data
1331 1346                   *  what's to read ?)
1332 1347                   */
1333 1348                  if (fn_dest->fn_flag & (FIFOWANTW | FIFOWANTR)) {
1334 1349                          fn_dest->fn_flag &= ~(FIFOWANTW | FIFOWANTR);
1335 1350                          cv_broadcast(&fn_dest->fn_wait_cv);
1336 1351                  }
1337 1352                  *rvalp = 0;
1338 1353                  break;
  
    | 
      ↓ open down ↓ | 
    199 lines elided | 
    
      ↑ open up ↑ | 
  
1339 1354  
1340 1355          /*
1341 1356           * Since no band data can ever get on a fifo in fast mode
1342 1357           * just return 0.
1343 1358           */
1344 1359          case I_FLUSHBAND:
1345 1360                  error = 0;
1346 1361                  *rvalp = 0;
1347 1362                  break;
1348 1363  
     1364 +        case _I_GETPEERCRED:
     1365 +                error = fifo_ioctl_getpeercred(fnp, arg, mode);
     1366 +                break;
     1367 +
1349 1368          /*
1350 1369           * invalid calls for stream head or fifos
1351 1370           */
1352 1371  
1353 1372          case I_POP:             /* shouldn't happen */
1354 1373          case I_LOOK:
1355 1374          case I_LINK:
1356 1375          case I_PLINK:
1357 1376          case I_UNLINK:
1358 1377          case I_PUNLINK:
1359 1378  
1360 1379          /*
1361 1380           * more invalid tty type of ioctls
1362 1381           */
1363 1382  
1364 1383          case SRIOCSREDIR:
1365 1384          case SRIOCISREDIR:
1366 1385                  error = EINVAL;
1367 1386                  break;
1368 1387  
1369 1388          }
1370 1389          mutex_exit(&fn_lock->flk_lock);
1371 1390          return (error);
1372 1391  
1373 1392  turn_fastoff:
1374 1393          fifo_fastoff(fnp);
1375 1394  
1376 1395  stream_mode:
1377 1396          /*
1378 1397           * streams mode
1379 1398           */
1380 1399          mutex_exit(&fn_lock->flk_lock);
1381 1400          return (fifo_strioctl(vp, cmd, arg, mode, cr, rvalp));
1382 1401  
1383 1402  }
1384 1403  
1385 1404  /*
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
1386 1405   * FIFO is in STREAMS mode; STREAMS framework does most of the work.
1387 1406   */
1388 1407  static int
1389 1408  fifo_strioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
1390 1409      int *rvalp)
1391 1410  {
1392 1411          fifonode_t      *fnp = VTOF(vp);
1393 1412          int             error;
1394 1413          fifolock_t      *fn_lock;
1395 1414  
1396      -        if (cmd == _I_GETPEERCRED) {
1397      -                if (mode == FKIOCTL && fnp->fn_pcredp != NULL) {
1398      -                        k_peercred_t *kp = (k_peercred_t *)arg;
1399      -                        crhold(fnp->fn_pcredp);
1400      -                        kp->pc_cr = fnp->fn_pcredp;
1401      -                        kp->pc_cpid = fnp->fn_cpid;
1402      -                        return (0);
1403      -                } else {
1404      -                        return (ENOTSUP);
1405      -                }
1406      -        }
     1415 +        if (cmd == _I_GETPEERCRED)
     1416 +                return (fifo_ioctl_getpeercred(fnp, arg, mode));
1407 1417  
1408 1418          error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp);
1409 1419  
1410 1420          switch (cmd) {
1411 1421          /*
1412 1422           * The FIFOSEND flag is set to inform other processes that a file
1413 1423           * descriptor is pending at the stream head of this pipe.
1414 1424           * The flag is cleared and the sending process is awoken when
1415 1425           * this process has completed receiving the file descriptor.
1416 1426           * XXX This could become out of sync if the process does I_SENDFDs
1417 1427           * and opens on connld attached to the same pipe.
1418 1428           */
1419 1429          case I_RECVFD:
1420 1430          case I_E_RECVFD:
1421 1431                  if (error == 0) {
1422 1432                          fn_lock = fnp->fn_lock;
1423 1433                          mutex_enter(&fn_lock->flk_lock);
1424 1434                          if (fnp->fn_flag & FIFOSEND) {
1425 1435                                  fnp->fn_flag &= ~FIFOSEND;
1426 1436                                  cv_broadcast(&fnp->fn_dest->fn_wait_cv);
1427 1437                          }
1428 1438                          mutex_exit(&fn_lock->flk_lock);
1429 1439                  }
1430 1440                  break;
1431 1441          default:
1432 1442                  break;
1433 1443          }
1434 1444  
1435 1445          return (error);
1436 1446  }
1437 1447  
1438 1448  /*
1439 1449   * If shadowing a vnode (FIFOs), apply the VOP_GETATTR to the shadowed
1440 1450   * vnode to Obtain the node information. If not shadowing (pipes), obtain
1441 1451   * the node information from the credentials structure.
1442 1452   */
1443 1453  int
1444 1454  fifo_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *crp,
1445 1455      caller_context_t *ct)
1446 1456  {
1447 1457          int             error           = 0;
1448 1458          fifonode_t      *fnp            = VTOF(vp);
1449 1459          queue_t         *qp;
1450 1460          qband_t         *bandp;
1451 1461          fifolock_t      *fn_lock        = fnp->fn_lock;
1452 1462  
1453 1463          if (fnp->fn_realvp) {
1454 1464                  /*
1455 1465                   * for FIFOs or mounted pipes
1456 1466                   */
1457 1467                  if (error = VOP_GETATTR(fnp->fn_realvp, vap, flags, crp, ct))
1458 1468                          return (error);
1459 1469                  mutex_enter(&fn_lock->flk_lock);
1460 1470                  /* set current times from fnode, even if older than vnode */
1461 1471                  vap->va_atime.tv_sec = fnp->fn_atime;
1462 1472                  vap->va_atime.tv_nsec = 0;
1463 1473                  vap->va_mtime.tv_sec = fnp->fn_mtime;
1464 1474                  vap->va_mtime.tv_nsec = 0;
1465 1475                  vap->va_ctime.tv_sec = fnp->fn_ctime;
1466 1476                  vap->va_ctime.tv_nsec = 0;
1467 1477          } else {
1468 1478                  /*
1469 1479                   * for non-attached/ordinary pipes
1470 1480                   */
1471 1481                  vap->va_mode = 0;
1472 1482                  mutex_enter(&fn_lock->flk_lock);
1473 1483                  vap->va_atime.tv_sec = fnp->fn_atime;
1474 1484                  vap->va_atime.tv_nsec = 0;
1475 1485                  vap->va_mtime.tv_sec = fnp->fn_mtime;
1476 1486                  vap->va_mtime.tv_nsec = 0;
1477 1487                  vap->va_ctime.tv_sec = fnp->fn_ctime;
1478 1488                  vap->va_ctime.tv_nsec = 0;
1479 1489                  vap->va_uid = crgetuid(crp);
1480 1490                  vap->va_gid = crgetgid(crp);
1481 1491                  vap->va_nlink = 0;
1482 1492                  vap->va_fsid = fifodev;
1483 1493                  vap->va_nodeid = (ino64_t)fnp->fn_ino;
1484 1494                  vap->va_rdev = 0;
1485 1495          }
1486 1496          vap->va_type = VFIFO;
1487 1497          vap->va_blksize = PIPE_BUF;
1488 1498          /*
1489 1499           * Size is number of un-read bytes at the stream head and
1490 1500           * nblocks is the unread bytes expressed in blocks.
1491 1501           */
1492 1502          if (vp->v_stream && (fnp->fn_flag & FIFOISOPEN)) {
1493 1503                  if ((fnp->fn_flag & FIFOFAST)) {
1494 1504                          vap->va_size = (u_offset_t)fnp->fn_count;
1495 1505                  } else {
1496 1506                          qp = RD((strvp2wq(vp)));
1497 1507                          vap->va_size = (u_offset_t)qp->q_count;
1498 1508                          if (qp->q_nband != 0) {
1499 1509                                  mutex_enter(QLOCK(qp));
1500 1510                                  for (bandp = qp->q_bandp; bandp;
1501 1511                                      bandp = bandp->qb_next)
1502 1512                                          vap->va_size += bandp->qb_count;
1503 1513                                  mutex_exit(QLOCK(qp));
1504 1514                          }
1505 1515                  }
1506 1516                  vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
1507 1517          } else {
1508 1518                  vap->va_size = (u_offset_t)0;
1509 1519                  vap->va_nblocks = (fsblkcnt64_t)0;
1510 1520          }
1511 1521          mutex_exit(&fn_lock->flk_lock);
1512 1522          vap->va_seq = 0;
1513 1523          return (0);
1514 1524  }
1515 1525  
1516 1526  /*
1517 1527   * If shadowing a vnode, apply the VOP_SETATTR to it, and to the fnode.
1518 1528   * Otherwise, set the time and return 0.
1519 1529   */
1520 1530  int
1521 1531  fifo_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *crp,
1522 1532      caller_context_t *ctp)
1523 1533  {
1524 1534          fifonode_t      *fnp    = VTOF(vp);
1525 1535          int             error   = 0;
1526 1536          fifolock_t      *fn_lock;
1527 1537  
1528 1538          if (fnp->fn_realvp)
1529 1539                  error = VOP_SETATTR(fnp->fn_realvp, vap, flags, crp, ctp);
1530 1540          if (error == 0) {
1531 1541                  fn_lock = fnp->fn_lock;
1532 1542                  mutex_enter(&fn_lock->flk_lock);
1533 1543                  if (vap->va_mask & AT_ATIME)
1534 1544                          fnp->fn_atime = vap->va_atime.tv_sec;
1535 1545                  if (vap->va_mask & AT_MTIME)
1536 1546                          fnp->fn_mtime = vap->va_mtime.tv_sec;
1537 1547                  fnp->fn_ctime = gethrestime_sec();
1538 1548                  mutex_exit(&fn_lock->flk_lock);
1539 1549          }
1540 1550          return (error);
1541 1551  }
1542 1552  
1543 1553  /*
1544 1554   * If shadowing a vnode, apply VOP_ACCESS to it.
1545 1555   * Otherwise, return 0 (allow all access).
1546 1556   */
1547 1557  int
1548 1558  fifo_access(vnode_t *vp, int mode, int flags, cred_t *crp, caller_context_t *ct)
1549 1559  {
1550 1560          if (VTOF(vp)->fn_realvp)
1551 1561                  return (VOP_ACCESS(VTOF(vp)->fn_realvp, mode, flags, crp, ct));
1552 1562          else
1553 1563                  return (0);
1554 1564  }
1555 1565  
1556 1566  /*
1557 1567   * This can be called if creat or an open with O_CREAT is done on the root
1558 1568   * of a lofs mount where the mounted entity is a fifo.
1559 1569   */
1560 1570  /*ARGSUSED*/
1561 1571  static int
1562 1572  fifo_create(struct vnode *dvp, char *name, vattr_t *vap, enum vcexcl excl,
1563 1573      int mode, struct vnode **vpp, struct cred *cr, int flag,
1564 1574      caller_context_t *ct, vsecattr_t *vsecp)
1565 1575  {
1566 1576          int error;
1567 1577  
1568 1578          ASSERT(dvp && (dvp->v_flag & VROOT) && *name == '\0');
1569 1579          if (excl == NONEXCL) {
1570 1580                  if (mode && (error = fifo_access(dvp, mode, 0, cr, ct)))
1571 1581                          return (error);
1572 1582                  VN_HOLD(dvp);
1573 1583                  return (0);
1574 1584          }
1575 1585          return (EEXIST);
1576 1586  }
1577 1587  
1578 1588  /*
1579 1589   * If shadowing a vnode, apply the VOP_FSYNC to it.
1580 1590   * Otherwise, return 0.
1581 1591   */
1582 1592  int
1583 1593  fifo_fsync(vnode_t *vp, int syncflag, cred_t *crp, caller_context_t *ct)
1584 1594  {
1585 1595          fifonode_t      *fnp    = VTOF(vp);
1586 1596          vattr_t         va;
1587 1597  
1588 1598          if (fnp->fn_realvp == NULL)
1589 1599                  return (0);
1590 1600  
1591 1601          bzero((caddr_t)&va, sizeof (va));
1592 1602          va.va_mask = AT_MTIME | AT_ATIME;
1593 1603          if (VOP_GETATTR(fnp->fn_realvp, &va, 0, crp, ct) == 0) {
1594 1604                  va.va_mask = 0;
1595 1605                  if (fnp->fn_mtime > va.va_mtime.tv_sec) {
1596 1606                          va.va_mtime.tv_sec = fnp->fn_mtime;
1597 1607                          va.va_mask = AT_MTIME;
1598 1608                  }
1599 1609                  if (fnp->fn_atime > va.va_atime.tv_sec) {
1600 1610                          va.va_atime.tv_sec = fnp->fn_atime;
1601 1611                          va.va_mask |= AT_ATIME;
1602 1612                  }
1603 1613                  if (va.va_mask != 0)
1604 1614                          (void) VOP_SETATTR(fnp->fn_realvp, &va, 0, crp, ct);
1605 1615          }
1606 1616          return (VOP_FSYNC(fnp->fn_realvp, syncflag, crp, ct));
1607 1617  }
1608 1618  
1609 1619  /*
1610 1620   * Called when the upper level no longer holds references to the
1611 1621   * vnode. Sync the file system and free the fifonode.
1612 1622   */
1613 1623  void
1614 1624  fifo_inactive(vnode_t *vp, cred_t *crp, caller_context_t *ct)
1615 1625  {
1616 1626          fifonode_t      *fnp;
1617 1627          fifolock_t      *fn_lock;
1618 1628  
1619 1629          mutex_enter(&ftable_lock);
1620 1630          mutex_enter(&vp->v_lock);
1621 1631          ASSERT(vp->v_count >= 1);
1622 1632          VN_RELE_LOCKED(vp);
1623 1633          if (vp->v_count != 0) {
1624 1634                  /*
1625 1635                   * Somebody accessed the fifo before we got a chance to
1626 1636                   * remove it.  They will remove it when they do a vn_rele.
1627 1637                   */
1628 1638                  mutex_exit(&vp->v_lock);
1629 1639                  mutex_exit(&ftable_lock);
1630 1640                  return;
1631 1641          }
1632 1642          mutex_exit(&vp->v_lock);
1633 1643  
1634 1644          fnp = VTOF(vp);
1635 1645  
1636 1646          /*
1637 1647           * remove fifo from fifo list so that no other process
1638 1648           * can grab it.
1639 1649           * Drop the reference count on the fifo node's
1640 1650           * underlying vfs.
1641 1651           */
1642 1652          if (fnp->fn_realvp) {
1643 1653                  (void) fiforemove(fnp);
1644 1654                  mutex_exit(&ftable_lock);
1645 1655                  (void) fifo_fsync(vp, FSYNC, crp, ct);
1646 1656                  VN_RELE(fnp->fn_realvp);
1647 1657                  VFS_RELE(vp->v_vfsp);
1648 1658                  vp->v_vfsp = NULL;
1649 1659          } else
1650 1660                  mutex_exit(&ftable_lock);
1651 1661  
1652 1662          fn_lock = fnp->fn_lock;
1653 1663  
1654 1664          mutex_enter(&fn_lock->flk_lock);
1655 1665          ASSERT(vp->v_stream == NULL);
1656 1666          ASSERT(vp->v_count == 0);
1657 1667          /*
1658 1668           * if this is last reference to the lock, then we can
1659 1669           * free everything up.
1660 1670           */
1661 1671          if (--fn_lock->flk_ref == 0) {
1662 1672                  mutex_exit(&fn_lock->flk_lock);
1663 1673                  ASSERT(fnp->fn_open == 0);
1664 1674                  ASSERT(fnp->fn_dest->fn_open == 0);
1665 1675                  if (fnp->fn_mp) {
1666 1676                          freemsg(fnp->fn_mp);
1667 1677                          fnp->fn_mp = NULL;
1668 1678                          fnp->fn_count = 0;
1669 1679                  }
1670 1680                  if (fnp->fn_pcredp != NULL) {
1671 1681                          crfree(fnp->fn_pcredp);
1672 1682                          fnp->fn_pcredp = NULL;
1673 1683                  }
1674 1684                  if (fnp->fn_flag & ISPIPE) {
1675 1685                          fifonode_t *fn_dest = fnp->fn_dest;
1676 1686  
1677 1687                          vp = FTOV(fn_dest);
1678 1688                          if (fn_dest->fn_mp) {
1679 1689                                  freemsg(fn_dest->fn_mp);
1680 1690                                  fn_dest->fn_mp = NULL;
1681 1691                                  fn_dest->fn_count = 0;
1682 1692                          }
1683 1693                          if (fn_dest->fn_pcredp != NULL) {
1684 1694                                  crfree(fn_dest->fn_pcredp);
1685 1695                                  fn_dest->fn_pcredp = NULL;
1686 1696                          }
1687 1697                          kmem_cache_free(pipe_cache, (fifodata_t *)fn_lock);
1688 1698                  } else
1689 1699                          kmem_cache_free(fnode_cache, (fifodata_t *)fn_lock);
1690 1700          } else {
1691 1701                  mutex_exit(&fn_lock->flk_lock);
1692 1702          }
1693 1703  }
1694 1704  
1695 1705  /*
1696 1706   * If shadowing a vnode, apply the VOP_FID to it.
1697 1707   * Otherwise, return EINVAL.
1698 1708   */
1699 1709  int
1700 1710  fifo_fid(vnode_t *vp, fid_t *fidfnp, caller_context_t *ct)
1701 1711  {
1702 1712          if (VTOF(vp)->fn_realvp)
1703 1713                  return (VOP_FID(VTOF(vp)->fn_realvp, fidfnp, ct));
1704 1714          else
1705 1715                  return (EINVAL);
1706 1716  }
1707 1717  
1708 1718  /*
1709 1719   * Lock a fifonode.
1710 1720   */
1711 1721  /* ARGSUSED */
1712 1722  int
1713 1723  fifo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
1714 1724  {
1715 1725          return (-1);
1716 1726  }
1717 1727  
1718 1728  /*
1719 1729   * Unlock a fifonode.
1720 1730   */
1721 1731  /* ARGSUSED */
1722 1732  void
1723 1733  fifo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
1724 1734  {
1725 1735  }
1726 1736  
1727 1737  /*
1728 1738   * Return error since seeks are not allowed on pipes.
1729 1739   */
1730 1740  /*ARGSUSED*/
1731 1741  int
1732 1742  fifo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
1733 1743  {
1734 1744          return (ESPIPE);
1735 1745  }
1736 1746  
1737 1747  /*
1738 1748   * If there is a realvp associated with vp, return it.
1739 1749   */
1740 1750  int
1741 1751  fifo_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
1742 1752  {
1743 1753          vnode_t *rvp;
1744 1754  
1745 1755          if ((rvp = VTOF(vp)->fn_realvp) != NULL) {
1746 1756                  vp = rvp;
1747 1757                  if (VOP_REALVP(vp, &rvp, ct) == 0)
1748 1758                          vp = rvp;
1749 1759          }
1750 1760  
1751 1761          *vpp = vp;
1752 1762          return (0);
1753 1763  }
1754 1764  
1755 1765  /*
1756 1766   * Poll for interesting events on a stream pipe
1757 1767   */
1758 1768  /* ARGSUSED */
1759 1769  int
1760 1770  fifo_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
1761 1771      pollhead_t **phpp, caller_context_t *ct)
1762 1772  {
1763 1773          fifonode_t      *fnp, *fn_dest;
1764 1774          fifolock_t      *fn_lock;
1765 1775          int             retevents;
1766 1776          struct stdata   *stp;
1767 1777  
1768 1778          ASSERT(vp->v_stream != NULL);
1769 1779  
1770 1780          stp = vp->v_stream;
1771 1781          retevents       = 0;
1772 1782          fnp             = VTOF(vp);
1773 1783          fn_dest         = fnp->fn_dest;
1774 1784          fn_lock         = fnp->fn_lock;
1775 1785  
1776 1786          if (polllock(&stp->sd_pollist, &fn_lock->flk_lock) != 0) {
1777 1787                  *reventsp = POLLNVAL;
1778 1788                  return (0);
1779 1789          }
1780 1790  
1781 1791          /*
1782 1792           * see if FIFO/pipe open
1783 1793           */
1784 1794          if ((fnp->fn_flag & FIFOISOPEN) == 0) {
1785 1795                  if (((events & (POLLIN | POLLRDNORM | POLLPRI | POLLRDBAND)) &&
1786 1796                      fnp->fn_rcnt == 0) ||
1787 1797                      ((events & (POLLWRNORM | POLLWRBAND)) &&
1788 1798                      fnp->fn_wcnt == 0)) {
1789 1799                          mutex_exit(&fnp->fn_lock->flk_lock);
1790 1800                          *reventsp = POLLERR;
1791 1801                          return (0);
1792 1802                  }
1793 1803          }
1794 1804  
1795 1805          /*
1796 1806           * if not in fast mode, let the stream head take care of it
1797 1807           */
1798 1808          if (!(fnp->fn_flag & FIFOFAST)) {
1799 1809                  mutex_exit(&fnp->fn_lock->flk_lock);
1800 1810                  goto stream_mode;
1801 1811          }
1802 1812  
1803 1813          /*
1804 1814           * If this is a pipe.. check to see if the other
1805 1815           * end is gone.  If we are a fifo, check to see
1806 1816           * if write end is gone.
1807 1817           */
1808 1818  
1809 1819          if ((fnp->fn_flag & ISPIPE) && (fn_dest->fn_open == 0)) {
1810 1820                  retevents = POLLHUP;
1811 1821          } else if ((fnp->fn_flag & (FIFOCLOSE | ISPIPE)) == FIFOCLOSE &&
1812 1822              (fn_dest->fn_wcnt == 0)) {
1813 1823                  /*
1814 1824                   * no writer at other end.
1815 1825                   * it was closed (versus yet to be opened)
1816 1826                   */
1817 1827                          retevents = POLLHUP;
1818 1828          } else if (events & (POLLWRNORM | POLLWRBAND)) {
1819 1829                  if (events & POLLWRNORM) {
1820 1830                          if (fn_dest->fn_count < Fifohiwat)
1821 1831                                  retevents = POLLWRNORM;
1822 1832                          else
1823 1833                                  fnp->fn_flag |= FIFOHIWATW;
1824 1834                  }
1825 1835                  /*
1826 1836                   * This is always true for fast pipes
1827 1837                   * (Note: will go to STREAMS mode if band data is written)
1828 1838                   */
1829 1839                  if (events & POLLWRBAND)
1830 1840                          retevents |= POLLWRBAND;
1831 1841          }
1832 1842          if (events & (POLLIN | POLLRDNORM)) {
1833 1843                  if (fnp->fn_count)
1834 1844                          retevents |= (events & (POLLIN | POLLRDNORM));
1835 1845          }
1836 1846  
1837 1847          /*
1838 1848           * if we happened to get something and we're not edge-triggered, return
1839 1849           */
1840 1850          if ((*reventsp = (short)retevents) != 0 && !(events & POLLET)) {
1841 1851                  mutex_exit(&fnp->fn_lock->flk_lock);
1842 1852                  return (0);
1843 1853          }
1844 1854  
1845 1855          /*
1846 1856           * If poll() has not found any events yet or we're edge-triggered, set
1847 1857           * up event cell to wake up the poll if a requested event occurs on this
1848 1858           * pipe/fifo.
1849 1859           */
1850 1860          if (!anyyet) {
1851 1861                  if (events & POLLWRNORM)
1852 1862                          fnp->fn_flag |= FIFOPOLLW;
1853 1863                  if (events & (POLLIN | POLLRDNORM))
1854 1864                          fnp->fn_flag |= FIFOPOLLR;
1855 1865                  if (events & POLLRDBAND)
1856 1866                          fnp->fn_flag |= FIFOPOLLRBAND;
1857 1867                  /*
1858 1868                   * XXX Don't like exposing this from streams
1859 1869                   */
1860 1870                  *phpp = &stp->sd_pollist;
1861 1871          }
1862 1872          mutex_exit(&fnp->fn_lock->flk_lock);
1863 1873          return (0);
1864 1874  stream_mode:
1865 1875          return (strpoll(stp, events, anyyet, reventsp, phpp));
1866 1876  }
1867 1877  
1868 1878  /*
1869 1879   * POSIX pathconf() support.
1870 1880   */
1871 1881  /* ARGSUSED */
1872 1882  int
1873 1883  fifo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
1874 1884      caller_context_t *ct)
1875 1885  {
1876 1886          ulong_t val;
1877 1887          int error = 0;
1878 1888  
1879 1889          switch (cmd) {
1880 1890  
1881 1891          case _PC_LINK_MAX:
1882 1892                  val = MAXLINK;
1883 1893                  break;
1884 1894  
1885 1895          case _PC_MAX_CANON:
1886 1896                  val = MAX_CANON;
1887 1897                  break;
1888 1898  
1889 1899          case _PC_MAX_INPUT:
1890 1900                  val = MAX_INPUT;
1891 1901                  break;
1892 1902  
1893 1903          case _PC_NAME_MAX:
1894 1904                  error = EINVAL;
1895 1905                  break;
1896 1906  
1897 1907          case _PC_PATH_MAX:
1898 1908          case _PC_SYMLINK_MAX:
1899 1909                  val = MAXPATHLEN;
1900 1910                  break;
1901 1911  
1902 1912          case _PC_PIPE_BUF:
1903 1913                  val = PIPE_BUF;
1904 1914                  break;
1905 1915  
1906 1916          case _PC_NO_TRUNC:
1907 1917                  if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC)
1908 1918                          val = 1;        /* NOTRUNC is enabled for vp */
1909 1919                  else
1910 1920                          val = (ulong_t)-1;
1911 1921                  break;
1912 1922  
1913 1923          case _PC_VDISABLE:
1914 1924                  val = _POSIX_VDISABLE;
1915 1925                  break;
1916 1926  
1917 1927          case _PC_CHOWN_RESTRICTED:
1918 1928                  if (rstchown)
1919 1929                          val = rstchown;         /* chown restricted enabled */
1920 1930                  else
1921 1931                          val = (ulong_t)-1;
1922 1932                  break;
1923 1933  
1924 1934          case _PC_FILESIZEBITS:
1925 1935                  val = (ulong_t)-1;
1926 1936                  break;
1927 1937  
1928 1938          default:
1929 1939                  if (VTOF(vp)->fn_realvp)
1930 1940                          error = VOP_PATHCONF(VTOF(vp)->fn_realvp, cmd,
1931 1941                              &val, cr, ct);
1932 1942                  else
1933 1943                          error = EINVAL;
1934 1944                  break;
1935 1945          }
1936 1946  
1937 1947          if (error == 0)
1938 1948                  *valp = val;
1939 1949          return (error);
1940 1950  }
1941 1951  
1942 1952  /*
1943 1953   * If shadowing a vnode, apply VOP_SETSECATTR to it.
1944 1954   * Otherwise, return NOSYS.
1945 1955   */
1946 1956  int
1947 1957  fifo_setsecattr(struct vnode *vp, vsecattr_t *vsap, int flag, struct cred *crp,
1948 1958      caller_context_t *ct)
1949 1959  {
1950 1960          int error;
1951 1961  
1952 1962          /*
1953 1963           * The acl(2) system call tries to grab the write lock on the
1954 1964           * file when setting an ACL, but fifofs does not implement
1955 1965           * VOP_RWLOCK or VOP_RWUNLOCK, so we do it here instead.
1956 1966           */
1957 1967          if (VTOF(vp)->fn_realvp) {
1958 1968                  (void) VOP_RWLOCK(VTOF(vp)->fn_realvp, V_WRITELOCK_TRUE, ct);
1959 1969                  error = VOP_SETSECATTR(VTOF(vp)->fn_realvp, vsap, flag,
1960 1970                      crp, ct);
1961 1971                  VOP_RWUNLOCK(VTOF(vp)->fn_realvp, V_WRITELOCK_TRUE, ct);
1962 1972                  return (error);
1963 1973          } else
1964 1974                  return (fs_nosys());
1965 1975  }
1966 1976  
1967 1977  /*
1968 1978   * If shadowing a vnode, apply VOP_GETSECATTR to it. Otherwise, fabricate
1969 1979   * an ACL from the permission bits that fifo_getattr() makes up.
1970 1980   */
1971 1981  int
1972 1982  fifo_getsecattr(struct vnode *vp, vsecattr_t *vsap, int flag, struct cred *crp,
1973 1983      caller_context_t *ct)
1974 1984  {
1975 1985          if (VTOF(vp)->fn_realvp)
1976 1986                  return (VOP_GETSECATTR(VTOF(vp)->fn_realvp, vsap, flag,
1977 1987                      crp, ct));
1978 1988          else
1979 1989                  return (fs_fab_acl(vp, vsap, flag, crp, ct));
1980 1990  }
1981 1991  
1982 1992  
1983 1993  /*
1984 1994   * Set the FIFOSTAYFAST flag so nobody can turn the fifo into stream mode.
1985 1995   * If the flag is already set then wait until it is removed - releasing
1986 1996   * the lock.
1987 1997   * If the fifo switches into stream mode while we are waiting, return failure.
1988 1998   */
1989 1999  static boolean_t
1990 2000  fifo_stayfast_enter(fifonode_t *fnp)
1991 2001  {
1992 2002          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
1993 2003          while (fnp->fn_flag & FIFOSTAYFAST) {
1994 2004                  fnp->fn_flag |= FIFOWAITMODE;
1995 2005                  cv_wait(&fnp->fn_wait_cv, &fnp->fn_lock->flk_lock);
1996 2006                  fnp->fn_flag &= ~FIFOWAITMODE;
1997 2007          }
1998 2008          if (!(fnp->fn_flag & FIFOFAST))
1999 2009                  return (B_FALSE);
2000 2010  
2001 2011          fnp->fn_flag |= FIFOSTAYFAST;
2002 2012          return (B_TRUE);
2003 2013  }
2004 2014  
2005 2015  /*
2006 2016   * Unset the FIFOSTAYFAST flag and notify anybody waiting for this flag
2007 2017   * to be removed:
2008 2018   *      - threads wanting to turn into stream mode waiting in fifo_fastoff(),
2009 2019   *      - other writers threads waiting in fifo_stayfast_enter().
2010 2020   */
2011 2021  static void
2012 2022  fifo_stayfast_exit(fifonode_t *fnp)
2013 2023  {
2014 2024          fifonode_t *fn_dest = fnp->fn_dest;
2015 2025  
2016 2026          ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
2017 2027  
2018 2028          fnp->fn_flag &= ~FIFOSTAYFAST;
2019 2029  
2020 2030          if (fnp->fn_flag & FIFOWAITMODE)
2021 2031                  cv_broadcast(&fnp->fn_wait_cv);
2022 2032  
2023 2033          if ((fnp->fn_flag & ISPIPE) && (fn_dest->fn_flag & FIFOWAITMODE))
2024 2034                  cv_broadcast(&fn_dest->fn_wait_cv);
2025 2035  }
  
    | 
      ↓ open down ↓ | 
    609 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX