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 = kmem_zalloc(sizeof (struct vfs), KM_SLEEP);
356 fifovfsp->vfs_next = NULL;
357 vfs_setops(fifovfsp, fifo_vfsops);
358 fifovfsp->vfs_vnodecovered = NULL;
359 fifovfsp->vfs_flag = 0;
360 fifovfsp->vfs_bsize = 1024;
361 fifovfsp->vfs_fstype = fifofstype;
362 vfs_make_fsid(&fifovfsp->vfs_fsid, fifodev, fifofstype);
363 fifovfsp->vfs_data = NULL;
364 fifovfsp->vfs_dev = fifodev;
365 fifovfsp->vfs_bcount = 0;
366
367 /*
368 * It is necessary to initialize vfs_count here to 1.
369 * This prevents the fifovfsp from getting freed when
370 * a thread does a VFS_HOLD followed by a VFS_RELE
371 * on the fifovfsp
372 *
373 * The fifovfsp should never be freed.
374 */
375 fifovfsp->vfs_count = 1;
376
377 mutex_init(&ftable_lock, NULL, MUTEX_DEFAULT, NULL);
378 mutex_init(&fino_lock, NULL, MUTEX_DEFAULT, NULL);
379
380 /*
381 * vnodes are cached aligned
382 */
383 fnode_cache = kmem_cache_create("fnode_cache",
384 sizeof (fifodata_t) - sizeof (fifonode_t), 32,
385 fnode_constructor, fnode_destructor, NULL,
386 (void *)(sizeof (fifodata_t) - sizeof (fifonode_t)), NULL, 0);
387
388 pipe_cache = kmem_cache_create("pipe_cache", sizeof (fifodata_t), 32,
389 pipe_constructor, pipe_destructor, NULL,
390 (void *)(sizeof (fifodata_t)), NULL, 0);
391
392 #if FIFODEBUG
393 if (Fifohiwat < FIFOHIWAT)
394 Fifohiwat = FIFOHIWAT;
395 #endif /* FIFODEBUG */
396 fifo_strdata.qi_minfo->mi_hiwat = Fifohiwat;
397
398 return (0);
399 }
400
401 /*
402 * Provide a shadow for a vnode. We create a new shadow before checking for an
403 * existing one, to minimize the amount of time we need to hold ftable_lock.
404 * If a vp already has a shadow in the hash list, return its shadow. If not,
405 * we hash the new vnode and return its pointer to the caller.
406 */
407 vnode_t *
fifovp(vnode_t * vp,cred_t * crp)408 fifovp(vnode_t *vp, cred_t *crp)
409 {
410 fifonode_t *fnp;
411 fifonode_t *spec_fnp; /* Speculative fnode ptr. */
412 fifodata_t *fdp;
413 vnode_t *newvp;
414 struct vattr va;
415 vnode_t *rvp;
416
417 ASSERT(vp != NULL);
418
419 fdp = kmem_cache_alloc(fnode_cache, KM_SLEEP);
420
421 fdp->fifo_lock.flk_ref = 1;
422 fnp = &fdp->fifo_fnode[0];
423
424 /*
425 * Its possible that fifo nodes on different lofs mountpoints
426 * shadow the same real filesystem fifo node.
427 * In this case its necessary to get and store the realvp.
428 * This way different fifo nodes sharing the same real vnode
429 * can use realvp for communication.
430 */
431
432 if (VOP_REALVP(vp, &rvp, NULL) == 0)
433 vp = rvp;
434
435 fnp->fn_realvp = vp;
436 fnp->fn_wcnt = 0;
437 fnp->fn_rcnt = 0;
438
439 #if FIFODEBUG
440 if (! Fifo_fastmode) {
441 fnp->fn_flag = 0;
442 } else {
443 fnp->fn_flag = FIFOFAST;
444 }
445 #else /* FIFODEBUG */
446 fnp->fn_flag = FIFOFAST;
447 #endif /* FIFODEBUG */
448
449 /*
450 * initialize the times from vp.
451 */
452 va.va_mask = AT_TIMES;
453 if (VOP_GETATTR(vp, &va, 0, crp, NULL) == 0) {
454 fnp->fn_atime = va.va_atime;
455 fnp->fn_mtime = va.va_mtime;
456 fnp->fn_ctime = va.va_ctime;
457 } else {
458 fnp->fn_atime.tv_sec = 0;
459 fnp->fn_atime.tv_nsec = 0;
460 fnp->fn_mtime.tv_sec = 0;
461 fnp->fn_mtime.tv_nsec = 0;
462 fnp->fn_ctime.tv_sec = 0;
463 fnp->fn_ctime.tv_nsec = 0;
464 }
465
466 /*
467 * Grab the VP here to avoid holding locks
468 * whilst trying to acquire others.
469 */
470
471 VN_HOLD(vp);
472
473 mutex_enter(&ftable_lock);
474
475 if ((spec_fnp = fifofind(vp)) != NULL) {
476 mutex_exit(&ftable_lock);
477
478 /*
479 * Release the vnode and free up our pre-prepared fnode.
480 * Zero the lock reference just to explicitly signal
481 * this is unused.
482 */
483 VN_RELE(vp);
484 fdp->fifo_lock.flk_ref = 0;
485 kmem_cache_free(fnode_cache, fdp);
486
487 return (FTOV(spec_fnp));
488 }
489
490 newvp = FTOV(fnp);
491 fifo_reinit_vp(newvp);
492 /*
493 * Since the fifo vnode's v_vfsp needs to point to the
494 * underlying filesystem's vfsp we need to bump up the
495 * underlying filesystem's vfs reference count.
496 * The count is decremented when the fifo node is
497 * inactivated.
498 */
499
500 VFS_HOLD(vp->v_vfsp);
501 newvp->v_vfsp = vp->v_vfsp;
502 newvp->v_rdev = vp->v_rdev;
503 newvp->v_flag |= (vp->v_flag & VROOT);
504
505 fifoinsert(fnp);
506 mutex_exit(&ftable_lock);
507
508 return (newvp);
509 }
510
511 /*
512 * Create a pipe end by...
513 * allocating a vnode-fifonode pair and initializing the fifonode.
514 */
515 void
makepipe(vnode_t ** vpp1,vnode_t ** vpp2)516 makepipe(vnode_t **vpp1, vnode_t **vpp2)
517 {
518 fifonode_t *fnp1;
519 fifonode_t *fnp2;
520 vnode_t *nvp1;
521 vnode_t *nvp2;
522 fifodata_t *fdp;
523 timestruc_t now;
524
525 fdp = kmem_cache_alloc(pipe_cache, KM_SLEEP);
526 fdp->fifo_lock.flk_ref = 2;
527 fnp1 = &fdp->fifo_fnode[0];
528 fnp2 = &fdp->fifo_fnode[1];
529
530 fnp1->fn_wcnt = fnp2->fn_wcnt = 1;
531 fnp1->fn_rcnt = fnp2->fn_rcnt = 1;
532 #if FIFODEBUG
533 if (! Fifo_fastmode) {
534 fnp1->fn_flag = fnp2->fn_flag = ISPIPE;
535 } else {
536 fnp1->fn_flag = fnp2->fn_flag = ISPIPE | FIFOFAST;
537 }
538 #else /* FIFODEBUG */
539 fnp1->fn_flag = fnp2->fn_flag = ISPIPE | FIFOFAST;
540 #endif /* FIFODEBUG */
541 gethrestime(&now);
542 fnp1->fn_atime = fnp2->fn_atime = now;
543 fnp1->fn_mtime = fnp2->fn_mtime = now;
544 fnp1->fn_ctime = fnp2->fn_ctime = now;
545
546 *vpp1 = nvp1 = FTOV(fnp1);
547 *vpp2 = nvp2 = FTOV(fnp2);
548
549 fifo_reinit_vp(nvp1); /* Reinitialize vnodes for reuse... */
550 fifo_reinit_vp(nvp2);
551 nvp1->v_vfsp = fifovfsp; /* Need to re-establish VFS & device */
552 nvp2->v_vfsp = fifovfsp; /* before we can reuse this vnode. */
553 nvp1->v_rdev = fifodev;
554 nvp2->v_rdev = fifodev;
555 }
556
557 /*
558 * Attempt to establish a unique pipe id. Only un-named pipes use this
559 * routine.
560 */
561 ino_t
fifogetid(void)562 fifogetid(void)
563 {
564 static ino_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
fifo_stropen(vnode_t ** vpp,int flag,cred_t * crp,int dotwist,int lockheld)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
fifo_cleanup(vnode_t * vp,int flag)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
fifoinsert(fifonode_t * fnp)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 *
fifofind(vnode_t * vp)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
fiforemove(fifonode_t * fnp)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
fifo_fastflush(fifonode_t * fnp)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
fifo_connld(struct vnode ** vpp,int flag,cred_t * crp)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
fifo_fastoff(fifonode_t * fnp)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
fifo_fastturnoff(fifonode_t * fnp)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
fifo_vfastoff(vnode_t * vp)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
fifo_wakewriter(fifonode_t * fn_dest,fifolock_t * fn_lock)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
fifo_wakereader(fifonode_t * fn_dest,fifolock_t * fn_lock)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 }
1210