10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51799Sgfaden * Common Development and Distribution License (the "License"). 61799Sgfaden * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 220Sstevel@tonic-gate 230Sstevel@tonic-gate /* 243898Srsb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 250Sstevel@tonic-gate * Use is subject to license terms. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * The routines defined in this file are supporting routines for FIFOFS 32*5331Samw * file system type. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate #include <sys/types.h> 350Sstevel@tonic-gate #include <sys/param.h> 360Sstevel@tonic-gate #include <sys/systm.h> 370Sstevel@tonic-gate #include <sys/debug.h> 380Sstevel@tonic-gate #include <sys/errno.h> 390Sstevel@tonic-gate #include <sys/time.h> 400Sstevel@tonic-gate #include <sys/kmem.h> 410Sstevel@tonic-gate #include <sys/inline.h> 420Sstevel@tonic-gate #include <sys/file.h> 430Sstevel@tonic-gate #include <sys/proc.h> 440Sstevel@tonic-gate #include <sys/stat.h> 450Sstevel@tonic-gate #include <sys/sysmacros.h> 460Sstevel@tonic-gate #include <sys/var.h> 470Sstevel@tonic-gate #include <sys/vfs.h> 483898Srsb #include <sys/vfs_opreg.h> 490Sstevel@tonic-gate #include <sys/vnode.h> 500Sstevel@tonic-gate #include <sys/mode.h> 510Sstevel@tonic-gate #include <sys/signal.h> 520Sstevel@tonic-gate #include <sys/user.h> 530Sstevel@tonic-gate #include <sys/uio.h> 540Sstevel@tonic-gate #include <sys/flock.h> 550Sstevel@tonic-gate #include <sys/stream.h> 560Sstevel@tonic-gate #include <sys/fs/fifonode.h> 570Sstevel@tonic-gate #include <sys/strsubr.h> 580Sstevel@tonic-gate #include <sys/stropts.h> 590Sstevel@tonic-gate #include <sys/cmn_err.h> 600Sstevel@tonic-gate #include <fs/fs_subr.h> 610Sstevel@tonic-gate #include <sys/ddi.h> 620Sstevel@tonic-gate 630Sstevel@tonic-gate 640Sstevel@tonic-gate #if FIFODEBUG 650Sstevel@tonic-gate int Fifo_fastmode = 1; /* pipes/fifos will be opened in fast mode */ 660Sstevel@tonic-gate int Fifo_verbose = 0; /* msg when switching out of fast mode */ 670Sstevel@tonic-gate int Fifohiwat = FIFOHIWAT; /* Modifiable FIFO high water mark */ 680Sstevel@tonic-gate #endif 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * This is the loadable module wrapper. 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate #include <sys/modctl.h> 740Sstevel@tonic-gate 750Sstevel@tonic-gate extern struct qinit fifo_strdata; 760Sstevel@tonic-gate 770Sstevel@tonic-gate struct vfsops *fifo_vfsops; 780Sstevel@tonic-gate 790Sstevel@tonic-gate static vfsdef_t vfw = { 800Sstevel@tonic-gate VFSDEF_VERSION, 810Sstevel@tonic-gate "fifofs", 820Sstevel@tonic-gate fifoinit, 830Sstevel@tonic-gate 0, 840Sstevel@tonic-gate NULL 850Sstevel@tonic-gate }; 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * Module linkage information for the kernel. 890Sstevel@tonic-gate */ 900Sstevel@tonic-gate extern struct mod_ops mod_fsops; 910Sstevel@tonic-gate 920Sstevel@tonic-gate static struct modlfs modlfs = { 930Sstevel@tonic-gate &mod_fsops, "filesystem for fifo", &vfw 940Sstevel@tonic-gate }; 950Sstevel@tonic-gate 960Sstevel@tonic-gate static struct modlinkage modlinkage = { 970Sstevel@tonic-gate MODREV_1, (void *)&modlfs, NULL 980Sstevel@tonic-gate }; 990Sstevel@tonic-gate 1000Sstevel@tonic-gate int 1010Sstevel@tonic-gate _init() 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate return (mod_install(&modlinkage)); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate int 1070Sstevel@tonic-gate _info(struct modinfo *modinfop) 1080Sstevel@tonic-gate { 1090Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * Define data structures within this file. 1140Sstevel@tonic-gate * XXX should the hash size be configurable ? 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate #define FIFOSHFT 5 1170Sstevel@tonic-gate #define FIFO_HASHSZ 63 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate #if ((FIFO_HASHSZ & (FIFO_HASHSZ - 1)) == 0) 1200Sstevel@tonic-gate #define FIFOHASH(vp) (((uintptr_t)(vp) >> FIFOSHFT) & (FIFO_HASHSZ - 1)) 1210Sstevel@tonic-gate #else 1220Sstevel@tonic-gate #define FIFOHASH(vp) (((uintptr_t)(vp) >> FIFOSHFT) % FIFO_HASHSZ) 1230Sstevel@tonic-gate #endif 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate fifonode_t *fifoalloc[FIFO_HASHSZ]; 1260Sstevel@tonic-gate dev_t fifodev; 1270Sstevel@tonic-gate struct vfs *fifovfsp; 1280Sstevel@tonic-gate int fifofstype; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate kmutex_t ftable_lock; 1310Sstevel@tonic-gate static kmutex_t fino_lock; 1320Sstevel@tonic-gate struct kmem_cache *fnode_cache; 1330Sstevel@tonic-gate struct kmem_cache *pipe_cache; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate static void fifoinsert(fifonode_t *); 1360Sstevel@tonic-gate static fifonode_t *fifofind(vnode_t *); 1370Sstevel@tonic-gate static int fifo_connld(struct vnode **, int, cred_t *); 1380Sstevel@tonic-gate static void fifo_fastturnoff(fifonode_t *); 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate static void fifo_reinit_vp(vnode_t *); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * Constructor/destructor routines for fifos and pipes. 1440Sstevel@tonic-gate * 1450Sstevel@tonic-gate * In the interest of code sharing, we define a common fifodata structure 1460Sstevel@tonic-gate * which consists of a fifolock and one or two fnodes. A fifo contains 1470Sstevel@tonic-gate * one fnode; a pipe contains two. The fifolock is shared by the fnodes, 1480Sstevel@tonic-gate * each of which points to it: 1490Sstevel@tonic-gate * 1500Sstevel@tonic-gate * --> --> --------- --- --- 1510Sstevel@tonic-gate * | | | lock | | | 1520Sstevel@tonic-gate * | | --------- | | 1530Sstevel@tonic-gate * | | | | fifo | 1540Sstevel@tonic-gate * | --- | fnode | | | 1550Sstevel@tonic-gate * | | | | pipe 1560Sstevel@tonic-gate * | --------- --- | 1570Sstevel@tonic-gate * | | | | 1580Sstevel@tonic-gate * ------- | fnode | | 1590Sstevel@tonic-gate * | | | 1600Sstevel@tonic-gate * --------- --- 1610Sstevel@tonic-gate * 1620Sstevel@tonic-gate * Since the fifolock is at the beginning of the fifodata structure, 1630Sstevel@tonic-gate * the fifolock address is the same as the fifodata address. Thus, 1640Sstevel@tonic-gate * we can determine the fifodata address from any of its member fnodes. 1650Sstevel@tonic-gate * This is essential for fifo_inactive. 1660Sstevel@tonic-gate * 167*5331Samw * The fnode constructor is designed to handle any fifodata structure, 1680Sstevel@tonic-gate * deducing the number of fnodes from the total size. Thus, the fnode 1690Sstevel@tonic-gate * constructor does most of the work for the pipe constructor. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate /*ARGSUSED1*/ 1720Sstevel@tonic-gate static int 1730Sstevel@tonic-gate fnode_constructor(void *buf, void *cdrarg, int kmflags) 1740Sstevel@tonic-gate { 1750Sstevel@tonic-gate fifodata_t *fdp = buf; 1760Sstevel@tonic-gate fifolock_t *flp = &fdp->fifo_lock; 1770Sstevel@tonic-gate fifonode_t *fnp = &fdp->fifo_fnode[0]; 1780Sstevel@tonic-gate size_t size = (uintptr_t)cdrarg; 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate mutex_init(&flp->flk_lock, NULL, MUTEX_DEFAULT, NULL); 1810Sstevel@tonic-gate cv_init(&flp->flk_wait_cv, NULL, CV_DEFAULT, NULL); 1820Sstevel@tonic-gate flp->flk_ocsync = 0; 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate while ((char *)fnp < (char *)buf + size) { 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate vnode_t *vp; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate vp = vn_alloc(KM_SLEEP); 1890Sstevel@tonic-gate fnp->fn_vnode = vp; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate fnp->fn_lock = flp; 1920Sstevel@tonic-gate fnp->fn_open = 0; 1930Sstevel@tonic-gate fnp->fn_dest = fnp; 1940Sstevel@tonic-gate fnp->fn_mp = NULL; 1950Sstevel@tonic-gate fnp->fn_count = 0; 1960Sstevel@tonic-gate fnp->fn_rsynccnt = 0; 1970Sstevel@tonic-gate fnp->fn_wsynccnt = 0; 1980Sstevel@tonic-gate fnp->fn_wwaitcnt = 0; 1990Sstevel@tonic-gate fnp->fn_insync = 0; 2000Sstevel@tonic-gate fnp->fn_pcredp = NULL; 2010Sstevel@tonic-gate fnp->fn_cpid = -1; 2020Sstevel@tonic-gate /* 2030Sstevel@tonic-gate * 32-bit stat(2) may fail if fn_ino isn't initialized 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate fnp->fn_ino = 0; 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate cv_init(&fnp->fn_wait_cv, NULL, CV_DEFAULT, NULL); 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate vn_setops(vp, fifo_vnodeops); 2100Sstevel@tonic-gate vp->v_stream = NULL; 2110Sstevel@tonic-gate vp->v_type = VFIFO; 2120Sstevel@tonic-gate vp->v_data = (caddr_t)fnp; 2130Sstevel@tonic-gate vp->v_flag = VNOMAP | VNOSWAP; 2140Sstevel@tonic-gate vn_exists(vp); 2150Sstevel@tonic-gate fnp++; 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate return (0); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate static void 2210Sstevel@tonic-gate fnode_destructor(void *buf, void *cdrarg) 2220Sstevel@tonic-gate { 2230Sstevel@tonic-gate fifodata_t *fdp = buf; 2240Sstevel@tonic-gate fifolock_t *flp = &fdp->fifo_lock; 2250Sstevel@tonic-gate fifonode_t *fnp = &fdp->fifo_fnode[0]; 2260Sstevel@tonic-gate size_t size = (uintptr_t)cdrarg; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate mutex_destroy(&flp->flk_lock); 2290Sstevel@tonic-gate cv_destroy(&flp->flk_wait_cv); 2300Sstevel@tonic-gate ASSERT(flp->flk_ocsync == 0); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate while ((char *)fnp < (char *)buf + size) { 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate vnode_t *vp = FTOV(fnp); 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate ASSERT(fnp->fn_mp == NULL); 2370Sstevel@tonic-gate ASSERT(fnp->fn_count == 0); 2380Sstevel@tonic-gate ASSERT(fnp->fn_lock == flp); 2390Sstevel@tonic-gate ASSERT(fnp->fn_open == 0); 2400Sstevel@tonic-gate ASSERT(fnp->fn_insync == 0); 2410Sstevel@tonic-gate ASSERT(fnp->fn_rsynccnt == 0 && fnp->fn_wsynccnt == 0); 2420Sstevel@tonic-gate ASSERT(fnp->fn_wwaitcnt == 0); 2430Sstevel@tonic-gate ASSERT(fnp->fn_pcredp == NULL); 2440Sstevel@tonic-gate ASSERT(vn_matchops(vp, fifo_vnodeops)); 2450Sstevel@tonic-gate ASSERT(vp->v_stream == NULL); 2460Sstevel@tonic-gate ASSERT(vp->v_type == VFIFO); 2470Sstevel@tonic-gate ASSERT(vp->v_data == (caddr_t)fnp); 2480Sstevel@tonic-gate ASSERT((vp->v_flag & (VNOMAP|VNOSWAP)) == (VNOMAP|VNOSWAP)); 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate cv_destroy(&fnp->fn_wait_cv); 2510Sstevel@tonic-gate vn_invalid(vp); 2520Sstevel@tonic-gate vn_free(vp); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate fnp++; 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate static int 2590Sstevel@tonic-gate pipe_constructor(void *buf, void *cdrarg, int kmflags) 2600Sstevel@tonic-gate { 2610Sstevel@tonic-gate fifodata_t *fdp = buf; 2620Sstevel@tonic-gate fifonode_t *fnp1 = &fdp->fifo_fnode[0]; 2630Sstevel@tonic-gate fifonode_t *fnp2 = &fdp->fifo_fnode[1]; 2640Sstevel@tonic-gate vnode_t *vp1; 2650Sstevel@tonic-gate vnode_t *vp2; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate (void) fnode_constructor(buf, cdrarg, kmflags); 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate vp1 = FTOV(fnp1); 2700Sstevel@tonic-gate vp2 = FTOV(fnp2); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate vp1->v_vfsp = vp2->v_vfsp = fifovfsp; 2730Sstevel@tonic-gate vp1->v_rdev = vp2->v_rdev = fifodev; 2740Sstevel@tonic-gate fnp1->fn_realvp = fnp2->fn_realvp = NULL; 2750Sstevel@tonic-gate fnp1->fn_dest = fnp2; 2760Sstevel@tonic-gate fnp2->fn_dest = fnp1; 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate return (0); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate static void 2820Sstevel@tonic-gate pipe_destructor(void *buf, void *cdrarg) 2830Sstevel@tonic-gate { 2840Sstevel@tonic-gate #ifdef DEBUG 2850Sstevel@tonic-gate fifodata_t *fdp = buf; 2860Sstevel@tonic-gate fifonode_t *fnp1 = &fdp->fifo_fnode[0]; 2870Sstevel@tonic-gate fifonode_t *fnp2 = &fdp->fifo_fnode[1]; 2880Sstevel@tonic-gate vnode_t *vp1 = FTOV(fnp1); 2890Sstevel@tonic-gate vnode_t *vp2 = FTOV(fnp2); 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate ASSERT(vp1->v_vfsp == fifovfsp); 2920Sstevel@tonic-gate ASSERT(vp2->v_vfsp == fifovfsp); 2930Sstevel@tonic-gate ASSERT(vp1->v_rdev == fifodev); 2940Sstevel@tonic-gate ASSERT(vp2->v_rdev == fifodev); 2950Sstevel@tonic-gate #endif 2960Sstevel@tonic-gate fnode_destructor(buf, cdrarg); 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * Reinitialize a FIFO vnode (uses normal vnode reinit, but ensures that 3010Sstevel@tonic-gate * vnode type and flags are reset). 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate static void fifo_reinit_vp(vnode_t *vp) 3050Sstevel@tonic-gate { 3060Sstevel@tonic-gate vn_reinit(vp); 3070Sstevel@tonic-gate vp->v_type = VFIFO; 3082712Snn35248 vp->v_flag &= VROOT; 3092712Snn35248 vp->v_flag |= VNOMAP | VNOSWAP; 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate /* 3130Sstevel@tonic-gate * Save file system type/index, initialize vfs operations vector, get 3140Sstevel@tonic-gate * unique device number for FIFOFS and initialize the FIFOFS hash. 3150Sstevel@tonic-gate * Create and initialize a "generic" vfs pointer that will be placed 3160Sstevel@tonic-gate * in the v_vfsp field of each pipe's vnode. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate int 3190Sstevel@tonic-gate fifoinit(int fstype, char *name) 3200Sstevel@tonic-gate { 3210Sstevel@tonic-gate static const fs_operation_def_t fifo_vfsops_template[] = { 3220Sstevel@tonic-gate NULL, NULL 3230Sstevel@tonic-gate }; 3240Sstevel@tonic-gate int error; 3250Sstevel@tonic-gate major_t dev; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate fifofstype = fstype; 3280Sstevel@tonic-gate error = vfs_setfsops(fstype, fifo_vfsops_template, &fifo_vfsops); 3290Sstevel@tonic-gate if (error != 0) { 3300Sstevel@tonic-gate cmn_err(CE_WARN, "fifoinit: bad vfs ops template"); 3310Sstevel@tonic-gate return (error); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate error = vn_make_ops(name, fifo_vnodeops_template, &fifo_vnodeops); 3350Sstevel@tonic-gate if (error != 0) { 3360Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 3370Sstevel@tonic-gate cmn_err(CE_WARN, "fifoinit: bad vnode ops template"); 3380Sstevel@tonic-gate return (error); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate if ((dev = getudev()) == (major_t)-1) { 3420Sstevel@tonic-gate cmn_err(CE_WARN, "fifoinit: can't get unique device number"); 3430Sstevel@tonic-gate dev = 0; 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate fifodev = makedevice(dev, 0); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate fifovfsp = kmem_zalloc(sizeof (struct vfs), KM_SLEEP); 3480Sstevel@tonic-gate fifovfsp->vfs_next = NULL; 3490Sstevel@tonic-gate vfs_setops(fifovfsp, fifo_vfsops); 3500Sstevel@tonic-gate fifovfsp->vfs_vnodecovered = NULL; 3510Sstevel@tonic-gate fifovfsp->vfs_flag = 0; 3520Sstevel@tonic-gate fifovfsp->vfs_bsize = 1024; 3530Sstevel@tonic-gate fifovfsp->vfs_fstype = fifofstype; 3540Sstevel@tonic-gate vfs_make_fsid(&fifovfsp->vfs_fsid, fifodev, fifofstype); 3550Sstevel@tonic-gate fifovfsp->vfs_data = NULL; 3560Sstevel@tonic-gate fifovfsp->vfs_dev = fifodev; 3570Sstevel@tonic-gate fifovfsp->vfs_bcount = 0; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate mutex_init(&ftable_lock, NULL, MUTEX_DEFAULT, NULL); 3600Sstevel@tonic-gate mutex_init(&fino_lock, NULL, MUTEX_DEFAULT, NULL); 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* 3630Sstevel@tonic-gate * vnodes are cached aligned 3640Sstevel@tonic-gate */ 3650Sstevel@tonic-gate fnode_cache = kmem_cache_create("fnode_cache", 3660Sstevel@tonic-gate sizeof (fifodata_t) - sizeof (fifonode_t), 32, 3670Sstevel@tonic-gate fnode_constructor, fnode_destructor, NULL, 3680Sstevel@tonic-gate (void *)(sizeof (fifodata_t) - sizeof (fifonode_t)), NULL, 0); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate pipe_cache = kmem_cache_create("pipe_cache", sizeof (fifodata_t), 32, 3710Sstevel@tonic-gate pipe_constructor, pipe_destructor, NULL, 3720Sstevel@tonic-gate (void *)(sizeof (fifodata_t)), NULL, 0); 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate #if FIFODEBUG 3750Sstevel@tonic-gate if (Fifohiwat < FIFOHIWAT) 3760Sstevel@tonic-gate Fifohiwat = FIFOHIWAT; 3770Sstevel@tonic-gate #endif /* FIFODEBUG */ 3780Sstevel@tonic-gate fifo_strdata.qi_minfo->mi_hiwat = Fifohiwat; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate return (0); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 384142Speterte * Provide a shadow for a vnode. We create a new shadow before checking for an 385142Speterte * existing one, to minimize the amount of time we need to hold ftable_lock. 386142Speterte * If a vp already has a shadow in the hash list, return its shadow. If not, 387142Speterte * we hash the new vnode and return its pointer to the caller. 3880Sstevel@tonic-gate */ 3890Sstevel@tonic-gate vnode_t * 3900Sstevel@tonic-gate fifovp(vnode_t *vp, cred_t *crp) 3910Sstevel@tonic-gate { 3920Sstevel@tonic-gate fifonode_t *fnp; 393142Speterte fifonode_t *spec_fnp; /* Speculative fnode ptr. */ 3940Sstevel@tonic-gate fifodata_t *fdp; 3950Sstevel@tonic-gate vnode_t *newvp; 3960Sstevel@tonic-gate struct vattr va; 3973947Snr123932 vnode_t *rvp; 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate ASSERT(vp != NULL); 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate fdp = kmem_cache_alloc(fnode_cache, KM_SLEEP); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate fdp->fifo_lock.flk_ref = 1; 4040Sstevel@tonic-gate fnp = &fdp->fifo_fnode[0]; 4051799Sgfaden 4061799Sgfaden /* 4073947Snr123932 * Its possible that fifo nodes on different lofs mountpoints 4083947Snr123932 * shadow the same real filesystem fifo node. 4093947Snr123932 * In this case its necessary to get and store the realvp. 4103947Snr123932 * This way different fifo nodes sharing the same real vnode 4113947Snr123932 * can use realvp for communication. 4121799Sgfaden */ 413*5331Samw 414*5331Samw if (VOP_REALVP(vp, &rvp, NULL) == 0) 415*5331Samw vp = rvp; 4161799Sgfaden 4170Sstevel@tonic-gate fnp->fn_realvp = vp; 4180Sstevel@tonic-gate fnp->fn_wcnt = 0; 4190Sstevel@tonic-gate fnp->fn_rcnt = 0; 420142Speterte 4210Sstevel@tonic-gate #if FIFODEBUG 4220Sstevel@tonic-gate if (! Fifo_fastmode) { 4230Sstevel@tonic-gate fnp->fn_flag = 0; 4240Sstevel@tonic-gate } else { 4250Sstevel@tonic-gate fnp->fn_flag = FIFOFAST; 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate #else /* FIFODEBUG */ 4280Sstevel@tonic-gate fnp->fn_flag = FIFOFAST; 4290Sstevel@tonic-gate #endif /* FIFODEBUG */ 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * initialize the times from vp. 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate va.va_mask = AT_TIMES; 435*5331Samw if (VOP_GETATTR(vp, &va, 0, crp, NULL) == 0) { 4360Sstevel@tonic-gate fnp->fn_atime = va.va_atime.tv_sec; 4370Sstevel@tonic-gate fnp->fn_mtime = va.va_mtime.tv_sec; 4380Sstevel@tonic-gate fnp->fn_ctime = va.va_ctime.tv_sec; 4390Sstevel@tonic-gate } else { 4400Sstevel@tonic-gate fnp->fn_atime = 0; 4410Sstevel@tonic-gate fnp->fn_mtime = 0; 4420Sstevel@tonic-gate fnp->fn_ctime = 0; 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate 445142Speterte /* 446142Speterte * Grab the VP here to avoid holding locks 447142Speterte * whilst trying to acquire others. 448142Speterte */ 449142Speterte 4500Sstevel@tonic-gate VN_HOLD(vp); 4510Sstevel@tonic-gate 452142Speterte mutex_enter(&ftable_lock); 453142Speterte 454142Speterte if ((spec_fnp = fifofind(vp)) != NULL) { 455142Speterte mutex_exit(&ftable_lock); 456142Speterte 457142Speterte /* 458142Speterte * Release the vnode and free up our pre-prepared fnode. 459142Speterte * Zero the lock reference just to explicitly signal 460142Speterte * this is unused. 461142Speterte */ 462142Speterte VN_RELE(vp); 463142Speterte fdp->fifo_lock.flk_ref = 0; 464142Speterte kmem_cache_free(fnode_cache, fdp); 465142Speterte 466142Speterte return (FTOV(spec_fnp)); 467142Speterte } 468142Speterte 4690Sstevel@tonic-gate newvp = FTOV(fnp); 4700Sstevel@tonic-gate fifo_reinit_vp(newvp); 4710Sstevel@tonic-gate newvp->v_vfsp = vp->v_vfsp; 4720Sstevel@tonic-gate newvp->v_rdev = vp->v_rdev; 4732712Snn35248 newvp->v_flag |= (vp->v_flag & VROOT); 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate fifoinsert(fnp); 4760Sstevel@tonic-gate mutex_exit(&ftable_lock); 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate return (newvp); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * Create a pipe end by... 4830Sstevel@tonic-gate * allocating a vnode-fifonode pair and initializing the fifonode. 4840Sstevel@tonic-gate */ 4850Sstevel@tonic-gate void 4860Sstevel@tonic-gate makepipe(vnode_t **vpp1, vnode_t **vpp2) 4870Sstevel@tonic-gate { 4880Sstevel@tonic-gate fifonode_t *fnp1; 4890Sstevel@tonic-gate fifonode_t *fnp2; 4900Sstevel@tonic-gate vnode_t *nvp1; 4910Sstevel@tonic-gate vnode_t *nvp2; 4920Sstevel@tonic-gate fifodata_t *fdp; 4930Sstevel@tonic-gate time_t now; 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate fdp = kmem_cache_alloc(pipe_cache, KM_SLEEP); 4960Sstevel@tonic-gate fdp->fifo_lock.flk_ref = 2; 4970Sstevel@tonic-gate fnp1 = &fdp->fifo_fnode[0]; 4980Sstevel@tonic-gate fnp2 = &fdp->fifo_fnode[1]; 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate fnp1->fn_wcnt = fnp2->fn_wcnt = 1; 5010Sstevel@tonic-gate fnp1->fn_rcnt = fnp2->fn_rcnt = 1; 5020Sstevel@tonic-gate #if FIFODEBUG 5030Sstevel@tonic-gate if (! Fifo_fastmode) { 5040Sstevel@tonic-gate fnp1->fn_flag = fnp2->fn_flag = ISPIPE; 5050Sstevel@tonic-gate } else { 5060Sstevel@tonic-gate fnp1->fn_flag = fnp2->fn_flag = ISPIPE | FIFOFAST; 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate #else /* FIFODEBUG */ 5090Sstevel@tonic-gate fnp1->fn_flag = fnp2->fn_flag = ISPIPE | FIFOFAST; 5100Sstevel@tonic-gate #endif /* FIFODEBUG */ 5110Sstevel@tonic-gate now = gethrestime_sec(); 5120Sstevel@tonic-gate fnp1->fn_atime = fnp2->fn_atime = now; 5130Sstevel@tonic-gate fnp1->fn_mtime = fnp2->fn_mtime = now; 5140Sstevel@tonic-gate fnp1->fn_ctime = fnp2->fn_ctime = now; 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate *vpp1 = nvp1 = FTOV(fnp1); 5170Sstevel@tonic-gate *vpp2 = nvp2 = FTOV(fnp2); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate fifo_reinit_vp(nvp1); /* Reinitialize vnodes for reuse... */ 5200Sstevel@tonic-gate fifo_reinit_vp(nvp2); 5210Sstevel@tonic-gate nvp1->v_vfsp = fifovfsp; /* Need to re-establish VFS & device */ 5220Sstevel@tonic-gate nvp2->v_vfsp = fifovfsp; /* before we can reuse this vnode. */ 5230Sstevel@tonic-gate nvp1->v_rdev = fifodev; 5240Sstevel@tonic-gate nvp2->v_rdev = fifodev; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * Attempt to establish a unique pipe id. Only un-named pipes use this 5290Sstevel@tonic-gate * routine. 5300Sstevel@tonic-gate */ 5310Sstevel@tonic-gate ino_t 5320Sstevel@tonic-gate fifogetid(void) 5330Sstevel@tonic-gate { 5340Sstevel@tonic-gate static ino_t fifo_ino = 0; 5350Sstevel@tonic-gate ino_t fino; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate mutex_enter(&fino_lock); 5380Sstevel@tonic-gate fino = fifo_ino++; 5390Sstevel@tonic-gate mutex_exit(&fino_lock); 5400Sstevel@tonic-gate return (fino); 5410Sstevel@tonic-gate } 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate /* 5450Sstevel@tonic-gate * Stream a pipe/FIFO. 5460Sstevel@tonic-gate * The FIFOCONNLD flag is used when CONNLD has been pushed on the stream. 5470Sstevel@tonic-gate * If the flag is set, a new vnode is created by calling fifo_connld(). 5480Sstevel@tonic-gate * Connld logic was moved to fifo_connld() to speed up the open 5490Sstevel@tonic-gate * operation, simplify the connld/fifo interaction, and remove inherent 5500Sstevel@tonic-gate * race conditions between the connld module and fifos. 5510Sstevel@tonic-gate * This routine is single threaded for two reasons. 5520Sstevel@tonic-gate * 1) connld requests are synchronous; that is, they must block 5530Sstevel@tonic-gate * until the server does an I_RECVFD (oh, well). Single threading is 5540Sstevel@tonic-gate * the simplest way to accomplish this. 5550Sstevel@tonic-gate * 2) fifo_close() must not send M_HANGUP or M_ERROR while we are 5560Sstevel@tonic-gate * in stropen. Stropen() has a tendency to reset things and 5570Sstevel@tonic-gate * we would like streams to remember that a hangup occurred. 5580Sstevel@tonic-gate */ 5590Sstevel@tonic-gate int 5600Sstevel@tonic-gate fifo_stropen(vnode_t **vpp, int flag, cred_t *crp, int dotwist, int lockheld) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate int error = 0; 5630Sstevel@tonic-gate vnode_t *oldvp = *vpp; 5640Sstevel@tonic-gate fifonode_t *fnp = VTOF(*vpp); 5650Sstevel@tonic-gate dev_t pdev = 0; 5660Sstevel@tonic-gate int firstopen = 0; 5670Sstevel@tonic-gate fifolock_t *fn_lock; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate fn_lock = fnp->fn_lock; 5700Sstevel@tonic-gate if (!lockheld) 5710Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 5720Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock)); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* 5750Sstevel@tonic-gate * FIFO is in the process of opening. Wait for it 5760Sstevel@tonic-gate * to complete before starting another open on it 5770Sstevel@tonic-gate * This prevents races associated with connld open 5780Sstevel@tonic-gate */ 5790Sstevel@tonic-gate while (fnp->fn_flag & FIFOOPEN) { 5800Sstevel@tonic-gate if (!cv_wait_sig(&fnp->fn_wait_cv, &fn_lock->flk_lock)) { 5810Sstevel@tonic-gate fifo_cleanup(oldvp, flag); 5820Sstevel@tonic-gate if (!lockheld) 5830Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 5840Sstevel@tonic-gate return (EINTR); 5850Sstevel@tonic-gate } 5860Sstevel@tonic-gate } 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate /* 5890Sstevel@tonic-gate * The other end of the pipe is almost closed so 5900Sstevel@tonic-gate * reject any other open on this end of the pipe 5910Sstevel@tonic-gate * This only happens with a pipe mounted under namefs 5920Sstevel@tonic-gate */ 5930Sstevel@tonic-gate if ((fnp->fn_flag & (FIFOCLOSE|ISPIPE)) == (FIFOCLOSE|ISPIPE)) { 5940Sstevel@tonic-gate fifo_cleanup(oldvp, flag); 5950Sstevel@tonic-gate cv_broadcast(&fnp->fn_wait_cv); 5960Sstevel@tonic-gate if (!lockheld) 5970Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 5980Sstevel@tonic-gate return (ENXIO); 5990Sstevel@tonic-gate } 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate fnp->fn_flag |= FIFOOPEN; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* 6040Sstevel@tonic-gate * can't allow close to happen while we are 6050Sstevel@tonic-gate * in the middle of stropen(). 6060Sstevel@tonic-gate * M_HANGUP and M_ERROR could leave the stream in a strange state 6070Sstevel@tonic-gate */ 6080Sstevel@tonic-gate while (fn_lock->flk_ocsync) 6090Sstevel@tonic-gate cv_wait(&fn_lock->flk_wait_cv, &fn_lock->flk_lock); 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate fn_lock->flk_ocsync = 1; 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate if (fnp->fn_flag & FIFOCONNLD) { 6140Sstevel@tonic-gate /* 6150Sstevel@tonic-gate * This is a reopen, so we should release the fifo lock 6160Sstevel@tonic-gate * just in case some strange module pushed on connld 6170Sstevel@tonic-gate * has some odd side effect. 6180Sstevel@tonic-gate * Note: this stropen is on the oldvp. It will 6190Sstevel@tonic-gate * have no impact on the connld vp returned and 6200Sstevel@tonic-gate * strclose() will only be called when we release 6210Sstevel@tonic-gate * flk_ocsync 6220Sstevel@tonic-gate */ 6230Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 6240Sstevel@tonic-gate if ((error = stropen(oldvp, &pdev, flag, crp)) != 0) { 6250Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 6260Sstevel@tonic-gate fifo_cleanup(oldvp, flag); 6270Sstevel@tonic-gate fn_lock->flk_ocsync = 0; 6280Sstevel@tonic-gate cv_broadcast(&fn_lock->flk_wait_cv); 6290Sstevel@tonic-gate goto out; 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate /* 6320Sstevel@tonic-gate * streams open done, allow close on other end if 6330Sstevel@tonic-gate * required. Do this now.. it could 6340Sstevel@tonic-gate * be a very long time before fifo_connld returns. 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 6370Sstevel@tonic-gate /* 6380Sstevel@tonic-gate * we need to fake an open here so that if this 6390Sstevel@tonic-gate * end of the pipe closes, we don't loose the 6400Sstevel@tonic-gate * stream head (kind of like single threading 6410Sstevel@tonic-gate * open and close for this end of the pipe) 6420Sstevel@tonic-gate * We'll need to call fifo_close() to do clean 6430Sstevel@tonic-gate * up in case this end of the pipe was closed 6440Sstevel@tonic-gate * down while we were in fifo_connld() 6450Sstevel@tonic-gate */ 6460Sstevel@tonic-gate ASSERT(fnp->fn_open > 0); 6470Sstevel@tonic-gate fnp->fn_open++; 6480Sstevel@tonic-gate fn_lock->flk_ocsync = 0; 6490Sstevel@tonic-gate cv_broadcast(&fn_lock->flk_wait_cv); 6500Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * Connld has been pushed onto the pipe 6530Sstevel@tonic-gate * Create new pipe on behalf of connld 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate if (error = fifo_connld(vpp, flag, crp)) { 656*5331Samw (void) fifo_close(oldvp, flag, 1, 0, crp, NULL); 6570Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 6580Sstevel@tonic-gate goto out; 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate /* 6610Sstevel@tonic-gate * undo fake open. We need to call fifo_close 6620Sstevel@tonic-gate * because some other thread could have done 6630Sstevel@tonic-gate * a close and detach of the named pipe while 6640Sstevel@tonic-gate * we were in fifo_connld(), so 6650Sstevel@tonic-gate * we want to make sure the close completes (yuk) 6660Sstevel@tonic-gate */ 667*5331Samw (void) fifo_close(oldvp, flag, 1, 0, crp, NULL); 6680Sstevel@tonic-gate /* 6690Sstevel@tonic-gate * fifo_connld has changed the vp, so we 6700Sstevel@tonic-gate * need to re-initialize locals 6710Sstevel@tonic-gate */ 6720Sstevel@tonic-gate fnp = VTOF(*vpp); 6730Sstevel@tonic-gate fn_lock = fnp->fn_lock; 6740Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 6750Sstevel@tonic-gate } else { 6760Sstevel@tonic-gate /* 6770Sstevel@tonic-gate * release lock in case there are modules pushed that 6780Sstevel@tonic-gate * could have some strange side effect 6790Sstevel@tonic-gate */ 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate /* 6840Sstevel@tonic-gate * If this is the first open of a fifo (dotwist 6850Sstevel@tonic-gate * will be non-zero) we will need to twist the queues. 6860Sstevel@tonic-gate */ 6870Sstevel@tonic-gate if (oldvp->v_stream == NULL) 6880Sstevel@tonic-gate firstopen = 1; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate /* 6920Sstevel@tonic-gate * normal open of pipe/fifo 6930Sstevel@tonic-gate */ 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate if ((error = stropen(oldvp, &pdev, flag, crp)) != 0) { 6960Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 6970Sstevel@tonic-gate fifo_cleanup(oldvp, flag); 6980Sstevel@tonic-gate ASSERT(fnp->fn_open != 0 || oldvp->v_stream == NULL); 6990Sstevel@tonic-gate fn_lock->flk_ocsync = 0; 7000Sstevel@tonic-gate cv_broadcast(&fn_lock->flk_wait_cv); 7010Sstevel@tonic-gate goto out; 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate /* 7060Sstevel@tonic-gate * twist the ends of the fifo together 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate if (dotwist && firstopen) 7090Sstevel@tonic-gate strmate(*vpp, *vpp); 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate /* 7120Sstevel@tonic-gate * Show that this open has succeeded 7130Sstevel@tonic-gate * and allow closes or other opens to proceed 7140Sstevel@tonic-gate */ 7150Sstevel@tonic-gate fnp->fn_open++; 7160Sstevel@tonic-gate fn_lock->flk_ocsync = 0; 7170Sstevel@tonic-gate cv_broadcast(&fn_lock->flk_wait_cv); 7180Sstevel@tonic-gate } 7190Sstevel@tonic-gate out: 7200Sstevel@tonic-gate fnp->fn_flag &= ~FIFOOPEN; 7210Sstevel@tonic-gate if (error == 0) { 7220Sstevel@tonic-gate fnp->fn_flag |= FIFOISOPEN; 7230Sstevel@tonic-gate /* 7240Sstevel@tonic-gate * If this is a FIFO and has the close flag set 7250Sstevel@tonic-gate * and there are now writers, clear the close flag 7260Sstevel@tonic-gate * Note: close flag only gets set when last writer 7270Sstevel@tonic-gate * on a FIFO goes away. 7280Sstevel@tonic-gate */ 7290Sstevel@tonic-gate if (((fnp->fn_flag & (ISPIPE|FIFOCLOSE)) == FIFOCLOSE) && 7300Sstevel@tonic-gate fnp->fn_wcnt > 0) 7310Sstevel@tonic-gate fnp->fn_flag &= ~FIFOCLOSE; 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate cv_broadcast(&fnp->fn_wait_cv); 7340Sstevel@tonic-gate if (!lockheld) 7350Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 7360Sstevel@tonic-gate return (error); 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate /* 7400Sstevel@tonic-gate * Clean up the state of a FIFO and/or mounted pipe in the 7410Sstevel@tonic-gate * event that a fifo_open() was interrupted while the 7420Sstevel@tonic-gate * process was blocked. 7430Sstevel@tonic-gate */ 7440Sstevel@tonic-gate void 7450Sstevel@tonic-gate fifo_cleanup(vnode_t *vp, int flag) 7460Sstevel@tonic-gate { 7470Sstevel@tonic-gate fifonode_t *fnp = VTOF(vp); 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock)); 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate cleanlocks(vp, curproc->p_pid, 0); 7520Sstevel@tonic-gate cleanshares(vp, curproc->p_pid); 7530Sstevel@tonic-gate if (flag & FREAD) { 7540Sstevel@tonic-gate fnp->fn_rcnt--; 7550Sstevel@tonic-gate } 7560Sstevel@tonic-gate if (flag & FWRITE) { 7570Sstevel@tonic-gate fnp->fn_wcnt--; 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate cv_broadcast(&fnp->fn_wait_cv); 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate /* 7640Sstevel@tonic-gate * Insert a fifonode-vnode pair onto the fifoalloc hash list. 7650Sstevel@tonic-gate */ 7660Sstevel@tonic-gate static void 7670Sstevel@tonic-gate fifoinsert(fifonode_t *fnp) 7680Sstevel@tonic-gate { 7690Sstevel@tonic-gate int idx = FIFOHASH(fnp->fn_realvp); 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate /* 7720Sstevel@tonic-gate * We don't need to hold fn_lock since we're holding ftable_lock and 7730Sstevel@tonic-gate * this routine is only called right after we've allocated an fnode. 7740Sstevel@tonic-gate * FIFO is inserted at head of NULL terminated doubly linked list. 7750Sstevel@tonic-gate */ 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftable_lock)); 7780Sstevel@tonic-gate fnp->fn_backp = NULL; 7790Sstevel@tonic-gate fnp->fn_nextp = fifoalloc[idx]; 7800Sstevel@tonic-gate fifoalloc[idx] = fnp; 7810Sstevel@tonic-gate if (fnp->fn_nextp) 7820Sstevel@tonic-gate fnp->fn_nextp->fn_backp = fnp; 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * Find a fifonode-vnode pair on the fifoalloc hash list. 7870Sstevel@tonic-gate * vp is a vnode to be shadowed. If it's on the hash list, 7880Sstevel@tonic-gate * it already has a shadow, therefore return its corresponding 7890Sstevel@tonic-gate * fifonode. 7900Sstevel@tonic-gate */ 7910Sstevel@tonic-gate static fifonode_t * 7920Sstevel@tonic-gate fifofind(vnode_t *vp) 7930Sstevel@tonic-gate { 7940Sstevel@tonic-gate fifonode_t *fnode; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftable_lock)); 7970Sstevel@tonic-gate for (fnode = fifoalloc[FIFOHASH(vp)]; fnode; fnode = fnode->fn_nextp) { 7980Sstevel@tonic-gate if (fnode->fn_realvp == vp) { 7990Sstevel@tonic-gate VN_HOLD(FTOV(fnode)); 8000Sstevel@tonic-gate return (fnode); 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate return (NULL); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate /* 8070Sstevel@tonic-gate * Remove a fifonode-vnode pair from the fifoalloc hash list. 8080Sstevel@tonic-gate * This routine is called from the fifo_inactive() routine when a 8090Sstevel@tonic-gate * FIFO is being released. 8100Sstevel@tonic-gate * If the link to be removed is the only link, set fifoalloc to NULL. 8110Sstevel@tonic-gate */ 8120Sstevel@tonic-gate void 8130Sstevel@tonic-gate fiforemove(fifonode_t *fnp) 8140Sstevel@tonic-gate { 8150Sstevel@tonic-gate int idx = FIFOHASH(fnp->fn_realvp); 8160Sstevel@tonic-gate fifonode_t *fnode; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ftable_lock)); 8190Sstevel@tonic-gate fnode = fifoalloc[idx]; 8200Sstevel@tonic-gate /* 8210Sstevel@tonic-gate * fast path... only 1 FIFO in this list entry 8220Sstevel@tonic-gate */ 8230Sstevel@tonic-gate if (fnode != NULL && fnode == fnp && 8240Sstevel@tonic-gate !fnode->fn_nextp && !fnode->fn_backp) { 8250Sstevel@tonic-gate fifoalloc[idx] = NULL; 8260Sstevel@tonic-gate } else { 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate for (; fnode; fnode = fnode->fn_nextp) { 8290Sstevel@tonic-gate if (fnode == fnp) { 8300Sstevel@tonic-gate /* 8310Sstevel@tonic-gate * if we are first entry 8320Sstevel@tonic-gate */ 8330Sstevel@tonic-gate if (fnp == fifoalloc[idx]) 8340Sstevel@tonic-gate fifoalloc[idx] = fnp->fn_nextp; 8350Sstevel@tonic-gate if (fnode->fn_nextp) 8360Sstevel@tonic-gate fnode->fn_nextp->fn_backp = 8370Sstevel@tonic-gate fnode->fn_backp; 8380Sstevel@tonic-gate if (fnode->fn_backp) 8390Sstevel@tonic-gate fnode->fn_backp->fn_nextp = 8400Sstevel@tonic-gate fnode->fn_nextp; 8410Sstevel@tonic-gate break; 8420Sstevel@tonic-gate } 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate } 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate /* 8480Sstevel@tonic-gate * Flush all data from a fifo's message queue 8490Sstevel@tonic-gate */ 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate void 8520Sstevel@tonic-gate fifo_fastflush(fifonode_t *fnp) 8530Sstevel@tonic-gate { 8540Sstevel@tonic-gate mblk_t *bp; 8550Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock)); 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate if ((bp = fnp->fn_mp) != NULL) { 8580Sstevel@tonic-gate fnp->fn_mp = NULL; 8590Sstevel@tonic-gate fnp->fn_count = 0; 8600Sstevel@tonic-gate freemsg(bp); 8610Sstevel@tonic-gate } 8620Sstevel@tonic-gate fifo_wakewriter(fnp->fn_dest, fnp->fn_lock); 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate /* 8660Sstevel@tonic-gate * Note: This routine is single threaded 8670Sstevel@tonic-gate * Protected by FIFOOPEN flag (i.e. flk_lock is not held) 8680Sstevel@tonic-gate * Upon successful completion, the original fifo is unlocked 8690Sstevel@tonic-gate * and FIFOOPEN is cleared for the original vpp. 8700Sstevel@tonic-gate * The new fifo returned has FIFOOPEN set. 8710Sstevel@tonic-gate */ 8720Sstevel@tonic-gate static int 8730Sstevel@tonic-gate fifo_connld(struct vnode **vpp, int flag, cred_t *crp) 8740Sstevel@tonic-gate { 8750Sstevel@tonic-gate struct vnode *vp1; 8760Sstevel@tonic-gate struct vnode *vp2; 8770Sstevel@tonic-gate struct fifonode *oldfnp; 8780Sstevel@tonic-gate struct fifonode *fn_dest; 8790Sstevel@tonic-gate int error; 8800Sstevel@tonic-gate struct file *filep; 8810Sstevel@tonic-gate struct fifolock *fn_lock; 8820Sstevel@tonic-gate cred_t *c; 8830Sstevel@tonic-gate 8840Sstevel@tonic-gate /* 8850Sstevel@tonic-gate * Get two vnodes that will represent the pipe ends for the new pipe. 8860Sstevel@tonic-gate */ 8870Sstevel@tonic-gate makepipe(&vp1, &vp2); 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate /* 8900Sstevel@tonic-gate * Allocate a file descriptor and file pointer for one of the pipe 8910Sstevel@tonic-gate * ends. The file descriptor will be used to send that pipe end to 8920Sstevel@tonic-gate * the process on the other end of this stream. Note that we get 8930Sstevel@tonic-gate * the file structure only, there is no file list entry allocated. 8940Sstevel@tonic-gate */ 8950Sstevel@tonic-gate if (error = falloc(vp1, FWRITE|FREAD, &filep, NULL)) { 8960Sstevel@tonic-gate VN_RELE(vp1); 8970Sstevel@tonic-gate VN_RELE(vp2); 8980Sstevel@tonic-gate return (error); 8990Sstevel@tonic-gate } 9000Sstevel@tonic-gate mutex_exit(&filep->f_tlock); 9010Sstevel@tonic-gate oldfnp = VTOF(*vpp); 9020Sstevel@tonic-gate fn_lock = oldfnp->fn_lock; 9030Sstevel@tonic-gate fn_dest = oldfnp->fn_dest; 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate /* 9060Sstevel@tonic-gate * Create two new stream heads and attach them to the two vnodes for 9070Sstevel@tonic-gate * the new pipe. 9080Sstevel@tonic-gate */ 9090Sstevel@tonic-gate if ((error = fifo_stropen(&vp1, FREAD|FWRITE, filep->f_cred, 0, 0)) != 9100Sstevel@tonic-gate 0 || 9110Sstevel@tonic-gate (error = fifo_stropen(&vp2, flag, filep->f_cred, 0, 0)) != 0) { 9120Sstevel@tonic-gate #if DEBUG 9130Sstevel@tonic-gate cmn_err(CE_NOTE, "fifo stropen failed error 0x%x", 9140Sstevel@tonic-gate error); 9150Sstevel@tonic-gate #endif 9160Sstevel@tonic-gate /* 9170Sstevel@tonic-gate * this will call fifo_close and VN_RELE on vp1 9180Sstevel@tonic-gate */ 9190Sstevel@tonic-gate (void) closef(filep); 9200Sstevel@tonic-gate VN_RELE(vp2); 9210Sstevel@tonic-gate return (error); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate /* 9250Sstevel@tonic-gate * twist the ends of the pipe together 9260Sstevel@tonic-gate */ 9270Sstevel@tonic-gate strmate(vp1, vp2); 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* 9300Sstevel@tonic-gate * Set our end to busy in open 9310Sstevel@tonic-gate * Note: Don't need lock around this because we're the only 9320Sstevel@tonic-gate * one who knows about it 9330Sstevel@tonic-gate */ 9340Sstevel@tonic-gate VTOF(vp2)->fn_flag |= FIFOOPEN; 9350Sstevel@tonic-gate 9360Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate fn_dest->fn_flag |= FIFOSEND; 9390Sstevel@tonic-gate /* 9400Sstevel@tonic-gate * check to make sure neither end of pipe has gone away 9410Sstevel@tonic-gate */ 9420Sstevel@tonic-gate if (!(fn_dest->fn_flag & FIFOISOPEN)) { 9430Sstevel@tonic-gate error = ENXIO; 9440Sstevel@tonic-gate fn_dest->fn_flag &= ~FIFOSEND; 9450Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 9460Sstevel@tonic-gate /* 9470Sstevel@tonic-gate * this will call fifo_close and VN_RELE on vp1 9480Sstevel@tonic-gate */ 9490Sstevel@tonic-gate goto out; 9500Sstevel@tonic-gate } 9510Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate /* 9540Sstevel@tonic-gate * Tag the sender's credential on the pipe descriptor. 9550Sstevel@tonic-gate */ 9560Sstevel@tonic-gate crhold(VTOF(vp1)->fn_pcredp = crp); 9570Sstevel@tonic-gate VTOF(vp1)->fn_cpid = curproc->p_pid; 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* 9600Sstevel@tonic-gate * send the file descriptor to other end of pipe 9610Sstevel@tonic-gate */ 9620Sstevel@tonic-gate if (error = do_sendfp((*vpp)->v_stream, filep, crp)) { 9630Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 9640Sstevel@tonic-gate fn_dest->fn_flag &= ~FIFOSEND; 9650Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 9660Sstevel@tonic-gate /* 9670Sstevel@tonic-gate * this will call fifo_close and VN_RELE on vp1 9680Sstevel@tonic-gate */ 9690Sstevel@tonic-gate goto out; 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate mutex_enter(&fn_lock->flk_lock); 9730Sstevel@tonic-gate /* 9740Sstevel@tonic-gate * Wait for other end to receive file descriptor 9750Sstevel@tonic-gate * FIFOCLOSE indicates that one or both sides of the pipe 9760Sstevel@tonic-gate * have gone away. 9770Sstevel@tonic-gate */ 9780Sstevel@tonic-gate while ((fn_dest->fn_flag & (FIFOCLOSE | FIFOSEND)) == FIFOSEND) { 9790Sstevel@tonic-gate if (!cv_wait_sig(&oldfnp->fn_wait_cv, &fn_lock->flk_lock)) { 9800Sstevel@tonic-gate error = EINTR; 9810Sstevel@tonic-gate fn_dest->fn_flag &= ~FIFOSEND; 9820Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 9830Sstevel@tonic-gate goto out; 9840Sstevel@tonic-gate } 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate /* 9870Sstevel@tonic-gate * If either end of pipe has gone away and the other end did not 9880Sstevel@tonic-gate * receive pipe, reject the connld open 9890Sstevel@tonic-gate */ 9900Sstevel@tonic-gate if ((fn_dest->fn_flag & FIFOSEND)) { 9910Sstevel@tonic-gate error = ENXIO; 9920Sstevel@tonic-gate fn_dest->fn_flag &= ~FIFOSEND; 9930Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 9940Sstevel@tonic-gate goto out; 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate oldfnp->fn_flag &= ~FIFOOPEN; 9980Sstevel@tonic-gate cv_broadcast(&oldfnp->fn_wait_cv); 9990Sstevel@tonic-gate mutex_exit(&fn_lock->flk_lock); 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate VN_RELE(*vpp); 10020Sstevel@tonic-gate *vpp = vp2; 10030Sstevel@tonic-gate (void) closef(filep); 10040Sstevel@tonic-gate return (0); 10050Sstevel@tonic-gate out: 10060Sstevel@tonic-gate c = filep->f_cred; 10070Sstevel@tonic-gate crhold(c); 10080Sstevel@tonic-gate (void) closef(filep); 10090Sstevel@tonic-gate VTOF(vp2)->fn_flag &= ~FIFOOPEN; 1010*5331Samw (void) fifo_close(vp2, flag, 1, (offset_t)0, c, NULL); 10110Sstevel@tonic-gate crfree(c); 10120Sstevel@tonic-gate VN_RELE(vp2); 10130Sstevel@tonic-gate return (error); 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate /* 10170Sstevel@tonic-gate * Disable fastpath mode. 10180Sstevel@tonic-gate */ 10190Sstevel@tonic-gate void 10200Sstevel@tonic-gate fifo_fastoff(fifonode_t *fnp) 10210Sstevel@tonic-gate { 10220Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock)); 10230Sstevel@tonic-gate ASSERT(FTOV(fnp)->v_stream); 10240Sstevel@tonic-gate 10252069Swroche /* FIFOSTAYFAST is set => FIFOFAST is set */ 10262069Swroche while ((fnp->fn_flag & FIFOSTAYFAST) || ((fnp->fn_flag & ISPIPE) && 10272069Swroche (fnp->fn_dest->fn_flag & FIFOSTAYFAST))) { 10282069Swroche ASSERT(fnp->fn_flag & FIFOFAST); 10292069Swroche /* indicate someone is waiting to turn into stream mode */ 10302069Swroche fnp->fn_flag |= FIFOWAITMODE; 10312069Swroche cv_wait(&fnp->fn_wait_cv, &fnp->fn_lock->flk_lock); 10322069Swroche fnp->fn_flag &= ~FIFOWAITMODE; 10332069Swroche } 10340Sstevel@tonic-gate 10352069Swroche /* as we may have relased the lock, test the FIFOFAST flag here */ 10360Sstevel@tonic-gate if (!(fnp->fn_flag & FIFOFAST)) 10370Sstevel@tonic-gate return; 10380Sstevel@tonic-gate #if FIFODEBUG 10390Sstevel@tonic-gate if (Fifo_verbose) 10400Sstevel@tonic-gate cmn_err(CE_NOTE, "Fifo reverting to streams mode\n"); 10410Sstevel@tonic-gate #endif 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate fifo_fastturnoff(fnp); 10440Sstevel@tonic-gate if (fnp->fn_flag & ISPIPE) { 10450Sstevel@tonic-gate fifo_fastturnoff(fnp->fn_dest); 10460Sstevel@tonic-gate } 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate /* 10510Sstevel@tonic-gate * flk_lock must be held while calling fifo_fastturnoff() to 10520Sstevel@tonic-gate * preserve data ordering (no reads or writes allowed) 10530Sstevel@tonic-gate */ 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate static void 10560Sstevel@tonic-gate fifo_fastturnoff(fifonode_t *fnp) 10570Sstevel@tonic-gate { 10580Sstevel@tonic-gate fifonode_t *fn_dest = fnp->fn_dest; 10590Sstevel@tonic-gate mblk_t *fn_mp; 10600Sstevel@tonic-gate int fn_flag; 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock)); 10630Sstevel@tonic-gate /* 10640Sstevel@tonic-gate * Note: This end can't be closed if there 10650Sstevel@tonic-gate * is stuff in fn_mp 10660Sstevel@tonic-gate */ 10670Sstevel@tonic-gate if ((fn_mp = fnp->fn_mp) != NULL) { 10680Sstevel@tonic-gate ASSERT(fnp->fn_flag & FIFOISOPEN); 10690Sstevel@tonic-gate ASSERT(FTOV(fnp)->v_stream != NULL); 10700Sstevel@tonic-gate ASSERT(FTOV(fnp)->v_stream->sd_wrq != NULL); 10710Sstevel@tonic-gate ASSERT(RD(FTOV(fnp)->v_stream->sd_wrq) != NULL); 10720Sstevel@tonic-gate ASSERT(strvp2wq(FTOV(fnp)) != NULL); 10730Sstevel@tonic-gate fnp->fn_mp = NULL; 10740Sstevel@tonic-gate fnp->fn_count = 0; 10750Sstevel@tonic-gate /* 10760Sstevel@tonic-gate * Don't need to drop flk_lock across the put() 10770Sstevel@tonic-gate * since we're just moving the message from the fifo 10780Sstevel@tonic-gate * node to the STREAM head... 10790Sstevel@tonic-gate */ 10800Sstevel@tonic-gate put(RD(strvp2wq(FTOV(fnp))), fn_mp); 10810Sstevel@tonic-gate } 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate /* 10840Sstevel@tonic-gate * Need to re-issue any pending poll requests 10850Sstevel@tonic-gate * so that the STREAMS framework sees them 10860Sstevel@tonic-gate * Writers would be waiting on fnp and readers on fn_dest 10870Sstevel@tonic-gate */ 10880Sstevel@tonic-gate if ((fnp->fn_flag & (FIFOISOPEN | FIFOPOLLW)) == 10890Sstevel@tonic-gate (FIFOISOPEN | FIFOPOLLW)) { 10900Sstevel@tonic-gate strpollwakeup(FTOV(fnp), POLLWRNORM); 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate fn_flag = fn_dest->fn_flag; 10930Sstevel@tonic-gate if ((fn_flag & FIFOISOPEN) == FIFOISOPEN) { 10940Sstevel@tonic-gate if ((fn_flag & (FIFOPOLLR | FIFOPOLLRBAND))) { 10950Sstevel@tonic-gate strpollwakeup(FTOV(fn_dest), POLLIN|POLLRDNORM); 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate /* 10990Sstevel@tonic-gate * wake up any sleeping processes so they can notice we went 11000Sstevel@tonic-gate * to streams mode 11010Sstevel@tonic-gate */ 11020Sstevel@tonic-gate fnp->fn_flag &= ~(FIFOFAST|FIFOWANTW|FIFOWANTR); 11030Sstevel@tonic-gate cv_broadcast(&fnp->fn_wait_cv); 11040Sstevel@tonic-gate } 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate /* 11070Sstevel@tonic-gate * Alternative version of fifo_fastoff() 11080Sstevel@tonic-gate * optimized for putmsg/getmsg. 11090Sstevel@tonic-gate */ 11100Sstevel@tonic-gate void 11110Sstevel@tonic-gate fifo_vfastoff(vnode_t *vp) 11120Sstevel@tonic-gate { 11130Sstevel@tonic-gate fifonode_t *fnp = VTOF(vp); 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate mutex_enter(&fnp->fn_lock->flk_lock); 11160Sstevel@tonic-gate if (!(fnp->fn_flag & FIFOFAST)) { 11170Sstevel@tonic-gate mutex_exit(&fnp->fn_lock->flk_lock); 11180Sstevel@tonic-gate return; 11190Sstevel@tonic-gate } 11200Sstevel@tonic-gate fifo_fastoff(fnp); 11210Sstevel@tonic-gate mutex_exit(&fnp->fn_lock->flk_lock); 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate /* 11250Sstevel@tonic-gate * Wake any sleeping writers, poll and send signals if necessary 11260Sstevel@tonic-gate * This module is only called when we drop below the hi water mark 11270Sstevel@tonic-gate * FIFOWANTW indicates that a process is sleeping in fifo_write() 11280Sstevel@tonic-gate * FIFOHIWATW indicates that we have either attempted a poll or 11290Sstevel@tonic-gate * non-blocking write and were over the high water mark 11300Sstevel@tonic-gate * This routine assumes a low water mark of 0. 11310Sstevel@tonic-gate */ 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate void 11340Sstevel@tonic-gate fifo_wakewriter(fifonode_t *fn_dest, fifolock_t *fn_lock) 11350Sstevel@tonic-gate { 11360Sstevel@tonic-gate int fn_dflag = fn_dest->fn_flag; 11370Sstevel@tonic-gate 11380Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fn_lock->flk_lock)); 11390Sstevel@tonic-gate ASSERT(fn_dest->fn_dest->fn_count < Fifohiwat); 11400Sstevel@tonic-gate if ((fn_dflag & FIFOWANTW)) { 11410Sstevel@tonic-gate cv_broadcast(&fn_dest->fn_wait_cv); 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate if ((fn_dflag & (FIFOHIWATW | FIFOISOPEN)) == 11440Sstevel@tonic-gate (FIFOHIWATW | FIFOISOPEN)) { 11450Sstevel@tonic-gate if (fn_dflag & FIFOPOLLW) 11460Sstevel@tonic-gate strpollwakeup(FTOV(fn_dest), POLLWRNORM); 11470Sstevel@tonic-gate if (fn_dflag & FIFOSETSIG) 11480Sstevel@tonic-gate str_sendsig(FTOV(fn_dest), S_WRNORM, 0, 0); 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate /* 11510Sstevel@tonic-gate * FIFOPOLLW can't be set without setting FIFOHIWAT 11520Sstevel@tonic-gate * This allows us to clear both here. 11530Sstevel@tonic-gate */ 11540Sstevel@tonic-gate fn_dest->fn_flag = fn_dflag & ~(FIFOWANTW | FIFOHIWATW | FIFOPOLLW); 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate /* 11580Sstevel@tonic-gate * wake up any sleeping readers, poll or send signal if needed 11590Sstevel@tonic-gate * FIFOWANTR indicates that a process is waiting in fifo_read() for data 11600Sstevel@tonic-gate * FIFOSETSIG indicates that SIGPOLL should be sent to process 11610Sstevel@tonic-gate * FIFOPOLLR indicates that a poll request for reading on the fifo was made 11620Sstevel@tonic-gate */ 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate void 11650Sstevel@tonic-gate fifo_wakereader(fifonode_t *fn_dest, fifolock_t *fn_lock) 11660Sstevel@tonic-gate { 11670Sstevel@tonic-gate int fn_dflag = fn_dest->fn_flag; 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fn_lock->flk_lock)); 11700Sstevel@tonic-gate if (fn_dflag & FIFOWANTR) { 11710Sstevel@tonic-gate cv_broadcast(&fn_dest->fn_wait_cv); 11720Sstevel@tonic-gate } 11730Sstevel@tonic-gate if (fn_dflag & FIFOISOPEN) { 11740Sstevel@tonic-gate if (fn_dflag & FIFOPOLLR) 11750Sstevel@tonic-gate strpollwakeup(FTOV(fn_dest), POLLIN | POLLRDNORM); 11760Sstevel@tonic-gate if (fn_dflag & FIFOSETSIG) 11770Sstevel@tonic-gate str_sendsig(FTOV(fn_dest), S_INPUT | S_RDNORM, 0, 0); 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate fn_dest->fn_flag = fn_dflag & ~(FIFOWANTR | FIFOPOLLR); 11800Sstevel@tonic-gate } 1181