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