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