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