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