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