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