Home | History | Annotate | Line # | Download | only in fifofs
      1 /*	$NetBSD: fifo_vnops.c,v 1.94 2026/10/02 03:53:00 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * Copyright (c) 1990, 1993, 1995
     31  *	The Regents of the University of California.  All rights reserved.
     32  *
     33  * Redistribution and use in source and binary forms, with or without
     34  * modification, are permitted provided that the following conditions
     35  * are met:
     36  * 1. Redistributions of source code must retain the above copyright
     37  *    notice, this list of conditions and the following disclaimer.
     38  * 2. Redistributions in binary form must reproduce the above copyright
     39  *    notice, this list of conditions and the following disclaimer in the
     40  *    documentation and/or other materials provided with the distribution.
     41  * 3. Neither the name of the University nor the names of its contributors
     42  *    may be used to endorse or promote products derived from this software
     43  *    without specific prior written permission.
     44  *
     45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     55  * SUCH DAMAGE.
     56  *
     57  *	@(#)fifo_vnops.c	8.10 (Berkeley) 5/27/95
     58  */
     59 
     60 #include <sys/cdefs.h>
     61 __KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.94 2026/10/02 03:53:00 riastradh Exp $");
     62 
     63 #include <sys/param.h>
     64 #include <sys/systm.h>
     65 #include <sys/proc.h>
     66 #include <sys/time.h>
     67 #include <sys/namei.h>
     68 #include <sys/vnode.h>
     69 #include <sys/socket.h>
     70 #include <sys/protosw.h>
     71 #include <sys/socketvar.h>
     72 #include <sys/stat.h>
     73 #include <sys/ioctl.h>
     74 #include <sys/file.h>
     75 #include <sys/errno.h>
     76 #include <sys/kmem.h>
     77 #include <sys/un.h>
     78 #include <sys/poll.h>
     79 #include <sys/event.h>
     80 #include <sys/condvar.h>
     81 
     82 #include <miscfs/fifofs/fifo.h>
     83 #include <miscfs/genfs/genfs.h>
     84 
     85 /*
     86  * This structure is associated with the FIFO vnode and stores
     87  * the state associated with the FIFO.
     88  */
     89 struct fifoinfo {
     90 	struct socket	*fi_readsock;
     91 	struct socket	*fi_writesock;
     92 	kcondvar_t	fi_rcv;
     93 	int		fi_readers;
     94 	kcondvar_t	fi_wcv;
     95 	int		fi_writers;
     96 	uint64_t	fi_rgen;
     97 	uint64_t	fi_wgen;
     98 };
     99 
    100 /*
    101  * Trivial lookup routine that always fails.
    102  */
    103 /* ARGSUSED */
    104 static int
    105 fifo_lookup(void *v)
    106 {
    107 	struct vop_lookup_v2_args /* {
    108 		struct vnode		*a_dvp;
    109 		struct vnode		**a_vpp;
    110 		struct componentname	*a_cnp;
    111 	} */ *ap = v;
    112 
    113 	*ap->a_vpp = NULL;
    114 	return (ENOTDIR);
    115 }
    116 
    117 /*
    118  * Open called to set up a new instance of a fifo or
    119  * to find an active instance of a fifo.
    120  */
    121 static int
    122 fifo_open(void *v)
    123 {
    124 	struct vop_open_args /* {
    125 		struct vnode	*a_vp;
    126 		int		a_mode;
    127 		kauth_cred_t	a_cred;
    128 	} */ *ap = v;
    129 	struct lwp	*l = curlwp;
    130 	struct vnode	*vp;
    131 	struct fifoinfo	*fip;
    132 	struct socket	*rso, *wso;
    133 	int		error;
    134 
    135 	vp = ap->a_vp;
    136 	KASSERT(VOP_ISLOCKED(vp));
    137 
    138 	if ((fip = vp->v_fifoinfo) == NULL) {
    139 		fip = kmem_alloc(sizeof(*fip), KM_SLEEP);
    140 		error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL);
    141 		if (error != 0) {
    142 			kmem_free(fip, sizeof(*fip));
    143 			return (error);
    144 		}
    145 		fip->fi_readsock = rso;
    146 		error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso);
    147 		if (error != 0) {
    148 			(void)soclose(rso);
    149 			kmem_free(fip, sizeof(*fip));
    150 			return (error);
    151 		}
    152 		fip->fi_writesock = wso;
    153 		solock(wso);
    154 		if ((error = unp_connect2(wso, rso)) != 0) {
    155 			sounlock(wso);
    156 			(void)soclose(wso);
    157 			(void)soclose(rso);
    158 			kmem_free(fip, sizeof(*fip));
    159 			return (error);
    160 		}
    161 
    162 		/*
    163 		 * FIFOs must be readable when there is at least 1
    164 		 * byte of data available in the receive buffer.
    165 		 *
    166 		 * FIFOs must be writable when there is space for
    167 		 * at least PIPE_BUF bytes in the send buffer.
    168 		 * If we're increasing the low water mark for the
    169 		 * send buffer, then mimic how soreserve() would
    170 		 * have set the high water mark.
    171 		 */
    172 		rso->so_rcv.sb_lowat = 1;
    173 		if (wso->so_snd.sb_lowat < PIPE_BUF) {
    174 			wso->so_snd.sb_hiwat = PIPE_BUF * 2;
    175 		}
    176 		wso->so_snd.sb_lowat = PIPE_BUF;
    177 
    178 		fip->fi_readers = 0;
    179 		fip->fi_writers = 0;
    180 		fip->fi_rgen = 0;
    181 		fip->fi_wgen = 0;
    182 		rso->so_state |= SS_CANTRCVMORE;
    183 		cv_init(&fip->fi_rcv, "fiford");
    184 		cv_init(&fip->fi_wcv, "fifowr");
    185 		vp->v_fifoinfo = fip;
    186 	} else {
    187 		wso = fip->fi_writesock;
    188 		rso = fip->fi_readsock;
    189 		solock(wso);
    190 	}
    191 
    192 	if (ap->a_mode & FREAD) {
    193 		if (fip->fi_readers++ == 0) {
    194 			wso->so_state &= ~SS_CANTSENDMORE;
    195 			cv_broadcast(&fip->fi_wcv);
    196 		}
    197 	}
    198 	if (ap->a_mode & FWRITE) {
    199 		if (fip->fi_writers++ == 0) {
    200 			rso->so_state &= ~SS_CANTRCVMORE;
    201 			cv_broadcast(&fip->fi_rcv);
    202 		}
    203 	}
    204 	if (ap->a_mode & FREAD) {
    205 		if (ap->a_mode & O_NONBLOCK) {
    206 		} else {
    207 			uint64_t wgen = fip->fi_wgen;
    208 
    209 			while (fip->fi_writers == 0 && wgen == fip->fi_wgen) {
    210 				VOP_UNLOCK(vp);
    211 				error = cv_wait_sig(&fip->fi_rcv,
    212 				    wso->so_lock);
    213 				sounlock(wso);
    214 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    215 				if (error && wgen == fip->fi_wgen)
    216 					goto bad;
    217 				solock(wso);
    218 			}
    219 		}
    220 		fip->fi_rgen++;
    221 	}
    222 	if (ap->a_mode & FWRITE) {
    223 		if (ap->a_mode & O_NONBLOCK) {
    224 			if (fip->fi_readers == 0) {
    225 				error = ENXIO;
    226 				sounlock(wso);
    227 				goto bad;
    228 			}
    229 		} else {
    230 			const uint64_t rgen = fip->fi_rgen;
    231 
    232 			while (fip->fi_readers == 0 && rgen == fip->fi_rgen) {
    233 				VOP_UNLOCK(vp);
    234 				error = cv_wait_sig(&fip->fi_wcv,
    235 				    wso->so_lock);
    236 				sounlock(wso);
    237 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    238 				if (error && rgen == fip->fi_rgen)
    239 					goto bad;
    240 				solock(wso);
    241 			}
    242 		}
    243 		fip->fi_wgen++;
    244 	}
    245 	sounlock(wso);
    246 	return (0);
    247  bad:
    248 	VOP_CLOSE(vp, ap->a_mode, ap->a_cred);
    249 	return (error);
    250 }
    251 
    252 /*
    253  * Vnode op for read
    254  */
    255 /* ARGSUSED */
    256 static int
    257 fifo_read(void *v)
    258 {
    259 	struct vop_read_args /* {
    260 		struct vnode	*a_vp;
    261 		struct uio	*a_uio;
    262 		int		a_ioflag;
    263 		kauth_cred_t	a_cred;
    264 	} */ *ap = v;
    265 	struct uio	*uio;
    266 	struct socket	*rso;
    267 	int		error, sflags;
    268 
    269 	uio = ap->a_uio;
    270 	rso = ap->a_vp->v_fifoinfo->fi_readsock;
    271 #ifdef DIAGNOSTIC
    272 	if (uio->uio_rw != UIO_READ)
    273 		panic("fifo_read mode");
    274 #endif
    275 	if (uio->uio_resid == 0)
    276 		return (0);
    277 	VOP_UNLOCK(ap->a_vp);
    278 	sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0;
    279 	error = (*rso->so_receive)(rso, NULL, uio, NULL, NULL, &sflags);
    280 	if (ap->a_ioflag & IO_NDELAY) {
    281 		if (error == EWOULDBLOCK &&
    282 		    ap->a_vp->v_fifoinfo->fi_writers == 0)
    283 			error = 0;
    284 	}
    285 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
    286 	return (error);
    287 }
    288 
    289 /*
    290  * Vnode op for write
    291  */
    292 /* ARGSUSED */
    293 static int
    294 fifo_write(void *v)
    295 {
    296 	struct vop_write_args /* {
    297 		struct vnode	*a_vp;
    298 		struct uio	*a_uio;
    299 		int		a_ioflag;
    300 		kauth_cred_t	a_cred;
    301 	} */ *ap = v;
    302 	struct socket	*wso;
    303 	int		error, sflags;
    304 
    305 	wso = ap->a_vp->v_fifoinfo->fi_writesock;
    306 #ifdef DIAGNOSTIC
    307 	if (ap->a_uio->uio_rw != UIO_WRITE)
    308 		panic("fifo_write mode");
    309 #endif
    310 	VOP_UNLOCK(ap->a_vp);
    311 	sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0;
    312 	error = (*wso->so_send)(wso, NULL, ap->a_uio, 0, NULL, sflags, curlwp);
    313 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
    314 	return (error);
    315 }
    316 
    317 /*
    318  * Device ioctl operation.
    319  */
    320 /* ARGSUSED */
    321 static int
    322 fifo_ioctl(void *v)
    323 {
    324 	struct vop_ioctl_args /* {
    325 		struct vnode	*a_vp;
    326 		u_long		a_command;
    327 		void		*a_data;
    328 		int		a_fflag;
    329 		kauth_cred_t	a_cred;
    330 		struct lwp	*a_l;
    331 	} */ *ap = v;
    332 	struct file	filetmp;
    333 	int		error;
    334 
    335 	if (ap->a_command == FIONBIO)
    336 		return (0);
    337 	if (ap->a_fflag & FREAD) {
    338 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
    339 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
    340 		if (error)
    341 			return (error);
    342 	}
    343 	if (ap->a_fflag & FWRITE) {
    344 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
    345 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
    346 		if (error)
    347 			return (error);
    348 	}
    349 	return (0);
    350 }
    351 
    352 /* ARGSUSED */
    353 static int
    354 fifo_poll(void *v)
    355 {
    356 	struct vop_poll_args /* {
    357 		struct vnode	*a_vp;
    358 		int		a_events;
    359 	} */ *ap = v;
    360 	struct socket	*rso = ap->a_vp->v_fifoinfo->fi_readsock;
    361 	struct socket	*wso = ap->a_vp->v_fifoinfo->fi_writesock;
    362 	struct socket	*lso = NULL;
    363 	int		events;
    364 
    365 	/*
    366 	 * N.B. We're using a slightly different naming convention
    367 	 * for these variables that most poll handlers.
    368 	 */
    369 	int		revents = 0;
    370 	int		wevents = 0;
    371 
    372 	if (rso != NULL) {
    373 		lso = rso;
    374 	} else if (wso != NULL) {
    375 		lso = wso;
    376 	}
    377 
    378 	if (lso == NULL) {
    379 		/* No associated sockets -> no events to report. */
    380 		return 0;
    381 	}
    382 
    383 	KASSERT(rso == NULL || lso->so_lock == rso->so_lock);
    384 	KASSERT(wso == NULL || lso->so_lock == wso->so_lock);
    385 
    386 	solock(lso);
    387 
    388 	if (rso != NULL) {
    389 		events = ap->a_events & (POLLIN | POLLRDNORM);
    390 		if (events != 0 && soreadable(rso)) {
    391 			revents |= events;
    392 		}
    393 		if (rso->so_state & SS_CANTRCVMORE) {
    394 			revents |= POLLHUP;
    395 		}
    396 		/*
    397 		 * We always selrecord the read side here regardless
    398 		 * of the caller's read interest because we need to
    399 		 * action POLLHUP.
    400 		 */
    401 		if (revents == 0) {
    402 			selrecord(curlwp, &rso->so_rcv.sb_sel);
    403 			rso->so_rcv.sb_flags |= SB_NOTIFY;
    404 		}
    405 	}
    406 
    407 	/* POSIX sez: POLLHUP and POLLOUT are mutually-exclusive. */
    408 	if (wso != NULL && (revents & POLLHUP) == 0) {
    409 		events = ap->a_events & (POLLOUT | POLLWRNORM);
    410 		if (events != 0 && sowritable(wso)) {
    411 			wevents |= events;
    412 		}
    413 		if (wevents == 0 && events != 0) {
    414 			selrecord(curlwp, &wso->so_snd.sb_sel);
    415 			wso->so_snd.sb_flags |= SB_NOTIFY;
    416 		}
    417 	}
    418 
    419 	sounlock(lso);
    420 
    421 	return (revents | wevents);
    422 }
    423 
    424 static int
    425 fifo_inactive(void *v)
    426 {
    427 	struct vop_inactive_v2_args /* {
    428 		struct vnode	*a_vp;
    429 		struct lwp	*a_l;
    430 	} */ *ap __unused = v;
    431 
    432 	return (0);
    433 }
    434 
    435 /*
    436  * This is a noop, simply returning what one has been given.
    437  */
    438 static int
    439 fifo_bmap(void *v)
    440 {
    441 	struct vop_bmap_args /* {
    442 		struct vnode	*a_vp;
    443 		daddr_t		a_bn;
    444 		struct vnode	**a_vpp;
    445 		daddr_t		*a_bnp;
    446 		int		*a_runp;
    447 	} */ *ap = v;
    448 
    449 	if (ap->a_vpp != NULL)
    450 		*ap->a_vpp = ap->a_vp;
    451 	if (ap->a_bnp != NULL)
    452 		*ap->a_bnp = ap->a_bn;
    453 	if (ap->a_runp != NULL)
    454 		*ap->a_runp = 0;
    455 	return (0);
    456 }
    457 
    458 /*
    459  * This is like socantrcvmore(), but we send the POLL_HUP code.
    460  */
    461 static void
    462 fifo_socantrcvmore(struct socket *so)
    463 {
    464 	KASSERT(solocked(so));
    465 
    466 	so->so_state |= SS_CANTRCVMORE;
    467 	if (sb_notify(&so->so_rcv)) {
    468 		sowakeup(so, &so->so_rcv, POLL_HUP);
    469 	}
    470 }
    471 
    472 /*
    473  * Device close routine
    474  */
    475 /* ARGSUSED */
    476 static int
    477 fifo_close(void *v)
    478 {
    479 	struct vop_close_args /* {
    480 		struct vnode	*a_vp;
    481 		int		a_fflag;
    482 		kauth_cred_t	a_cred;
    483 		struct lwp	*a_l;
    484 	} */ *ap = v;
    485 	struct vnode	*vp;
    486 	struct fifoinfo	*fip;
    487 	struct socket *wso, *rso;
    488 	int isrevoke;
    489 
    490 	vp = ap->a_vp;
    491 	fip = vp->v_fifoinfo;
    492 	isrevoke = (ap->a_fflag & (FREAD | FWRITE | FNONBLOCK)) == FNONBLOCK;
    493 	wso = fip->fi_writesock;
    494 	rso = fip->fi_readsock;
    495 	solock(wso);
    496 	if (isrevoke) {
    497 		if (fip->fi_readers != 0) {
    498 			fip->fi_readers = 0;
    499 			socantsendmore(wso);
    500 		}
    501 		if (fip->fi_writers != 0) {
    502 			fip->fi_writers = 0;
    503 			fifo_socantrcvmore(rso);
    504 		}
    505 	} else {
    506 		if ((ap->a_fflag & FREAD) && --fip->fi_readers == 0)
    507 			socantsendmore(wso);
    508 		if ((ap->a_fflag & FWRITE) && --fip->fi_writers == 0)
    509 			fifo_socantrcvmore(rso);
    510 	}
    511 	if ((fip->fi_readers + fip->fi_writers) == 0) {
    512 		sounlock(wso);
    513 		(void) soclose(rso);
    514 		(void) soclose(wso);
    515 		cv_destroy(&fip->fi_rcv);
    516 		cv_destroy(&fip->fi_wcv);
    517 		kmem_free(fip, sizeof(*fip));
    518 		vp->v_fifoinfo = NULL;
    519 	} else
    520 		sounlock(wso);
    521 	return (0);
    522 }
    523 
    524 /*
    525  * Print out internal contents of a fifo vnode.
    526  */
    527 static void
    528 fifo_printinfo(struct vnode *vp)
    529 {
    530 	struct fifoinfo	*fip;
    531 
    532 	fip = vp->v_fifoinfo;
    533 	printf(", fifo with %d readers and %d writers",
    534 	    fip->fi_readers, fip->fi_writers);
    535 }
    536 
    537 /*
    538  * Print out the contents of a fifo vnode.
    539  */
    540 static int
    541 fifo_print(void *v)
    542 {
    543 	struct vop_print_args /* {
    544 		struct vnode	*a_vp;
    545 	} */ *ap = v;
    546 
    547 	/*
    548 	 * We are most likely being called with the vnode belonging
    549 	 * to some file system and this is not printed.
    550 	 */
    551 	if (ap->a_vp->v_tag == VT_NON)
    552 		printf("tag VT_NON");
    553 
    554 	fifo_printinfo(ap->a_vp);
    555 	printf("\n");
    556 	return 0;
    557 }
    558 
    559 /*
    560  * Return POSIX pathconf information applicable to fifo's.
    561  */
    562 static int
    563 fifo_pathconf(void *v)
    564 {
    565 	struct vop_pathconf_args /* {
    566 		struct vnode	*a_vp;
    567 		int		a_name;
    568 		register_t	*a_retval;
    569 	} */ *ap = v;
    570 
    571 	switch (ap->a_name) {
    572 	case _PC_LINK_MAX:
    573 		*ap->a_retval = LINK_MAX;
    574 		return (0);
    575 	case _PC_PIPE_BUF:
    576 		*ap->a_retval = PIPE_BUF;
    577 		return (0);
    578 	case _PC_CHOWN_RESTRICTED:
    579 		*ap->a_retval = 1;
    580 		return (0);
    581 	case _PC_SYNC_IO:
    582 		*ap->a_retval = 1;
    583 		return (0);
    584 	default:
    585 		return genfs_pathconf(ap);
    586 	}
    587 	/* NOTREACHED */
    588 }
    589 
    590 static void
    591 filt_fifordetach(struct knote *kn)
    592 {
    593 	struct socket *so;
    594 
    595 	so = (struct socket *)kn->kn_hook;
    596 	solock(so);
    597 	if (selremove_knote(&so->so_rcv.sb_sel, kn))
    598 		so->so_rcv.sb_flags &= ~SB_KNOTE;
    599 	sounlock(so);
    600 }
    601 
    602 static int
    603 filt_fiforead(struct knote *kn, long hint)
    604 {
    605 	struct socket *so;
    606 	int rv;
    607 
    608 	so = (struct socket *)kn->kn_hook;
    609 	if (hint != NOTE_SUBMIT)
    610 		solock(so);
    611 	kn->kn_data = so->so_rcv.sb_cc;
    612 	if (so->so_state & SS_CANTRCVMORE) {
    613 		knote_set_eof(kn, 0);
    614 		rv = 1;
    615 	} else {
    616 		knote_clear_eof(kn);
    617 		rv = (kn->kn_data >= so->so_rcv.sb_lowat);
    618 	}
    619 	if (hint != NOTE_SUBMIT)
    620 		sounlock(so);
    621 	return rv;
    622 }
    623 
    624 static void
    625 filt_fifowdetach(struct knote *kn)
    626 {
    627 	struct socket *so;
    628 
    629 	so = (struct socket *)kn->kn_hook;
    630 	solock(so);
    631 	if (selremove_knote(&so->so_snd.sb_sel, kn))
    632 		so->so_snd.sb_flags &= ~SB_KNOTE;
    633 	sounlock(so);
    634 }
    635 
    636 static int
    637 filt_fifowrite(struct knote *kn, long hint)
    638 {
    639 	struct socket *so;
    640 	int rv;
    641 
    642 	so = (struct socket *)kn->kn_hook;
    643 	if (hint != NOTE_SUBMIT)
    644 		solock(so);
    645 	kn->kn_data = sbspace(&so->so_snd);
    646 	if (so->so_state & SS_CANTSENDMORE) {
    647 		knote_set_eof(kn, 0);
    648 		rv = 1;
    649 	} else {
    650 		knote_clear_eof(kn);
    651 		rv = (kn->kn_data >= so->so_snd.sb_lowat);
    652 	}
    653 	if (hint != NOTE_SUBMIT)
    654 		sounlock(so);
    655 	return rv;
    656 }
    657 
    658 static const struct filterops fiforead_filtops = {
    659 	.f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
    660 	.f_attach = NULL,
    661 	.f_detach = filt_fifordetach,
    662 	.f_event = filt_fiforead,
    663 };
    664 
    665 static const struct filterops fifowrite_filtops = {
    666 	.f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
    667 	.f_attach = NULL,
    668 	.f_detach = filt_fifowdetach,
    669 	.f_event = filt_fifowrite,
    670 };
    671 
    672 /* ARGSUSED */
    673 static int
    674 fifo_kqfilter(void *v)
    675 {
    676 	struct vop_kqfilter_args /* {
    677 		struct vnode *a_vp;
    678 		struct knote *a_kn;
    679 	} */ *ap = v;
    680 	struct socket	*so;
    681 	struct sockbuf	*sb;
    682 
    683 	switch (ap->a_kn->kn_filter) {
    684 	case EVFILT_READ:
    685 		so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
    686 		ap->a_kn->kn_fop = &fiforead_filtops;
    687 		sb = &so->so_rcv;
    688 		break;
    689 	case EVFILT_WRITE:
    690 		so = (struct socket *)ap->a_vp->v_fifoinfo->fi_writesock;
    691 		ap->a_kn->kn_fop = &fifowrite_filtops;
    692 		sb = &so->so_snd;
    693 		break;
    694 	default:
    695 		return (EINVAL);
    696 	}
    697 
    698 	ap->a_kn->kn_hook = so;
    699 
    700 	solock(so);
    701 	selrecord_knote(&sb->sb_sel, ap->a_kn);
    702 	sb->sb_flags |= SB_KNOTE;
    703 	sounlock(so);
    704 
    705 	return (0);
    706 }
    707 
    708 int (**fifo_vnodeop_p)(void *);
    709 const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
    710 	{ &vop_default_desc, vn_default_error },
    711 	{ &vop_parsepath_desc, genfs_parsepath },	/* parsepath */
    712 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
    713 	{ &vop_create_desc, genfs_badop },		/* create */
    714 	{ &vop_mknod_desc, genfs_badop },		/* mknod */
    715 	{ &vop_open_desc, fifo_open },			/* open */
    716 	{ &vop_close_desc, fifo_close },		/* close */
    717 	{ &vop_access_desc, genfs_ebadf },		/* access */
    718 	{ &vop_accessx_desc, genfs_accessx },		/* accessx */
    719 	{ &vop_getattr_desc, genfs_ebadf },		/* getattr */
    720 	{ &vop_setattr_desc, genfs_ebadf },		/* setattr */
    721 	{ &vop_read_desc, fifo_read },			/* read */
    722 	{ &vop_write_desc, fifo_write },		/* write */
    723 	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
    724 	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
    725 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
    726 	{ &vop_poll_desc, fifo_poll },			/* poll */
    727 	{ &vop_kqfilter_desc, fifo_kqfilter },		/* kqfilter */
    728 	{ &vop_revoke_desc, genfs_revoke },		/* revoke */
    729 	{ &vop_mmap_desc, genfs_badop },		/* mmap */
    730 	{ &vop_fsync_desc, genfs_nullop },		/* fsync */
    731 	{ &vop_seek_desc, genfs_badop },		/* seek */
    732 	{ &vop_remove_desc, genfs_badop },		/* remove */
    733 	{ &vop_link_desc, genfs_badop },		/* link */
    734 	{ &vop_rename_desc, genfs_badop },		/* rename */
    735 	{ &vop_mkdir_desc, genfs_badop },		/* mkdir */
    736 	{ &vop_rmdir_desc, genfs_badop },		/* rmdir */
    737 	{ &vop_symlink_desc, genfs_badop },		/* symlink */
    738 	{ &vop_readdir_desc, genfs_badop },		/* readdir */
    739 	{ &vop_readlink_desc, genfs_badop },		/* readlink */
    740 	{ &vop_abortop_desc, genfs_badop },		/* abortop */
    741 	{ &vop_inactive_desc, fifo_inactive },		/* inactive */
    742 	{ &vop_reclaim_desc, genfs_nullop },		/* reclaim */
    743 	{ &vop_lock_desc, genfs_lock },			/* lock */
    744 	{ &vop_unlock_desc, genfs_unlock },		/* unlock */
    745 	{ &vop_bmap_desc, fifo_bmap },			/* bmap */
    746 	{ &vop_strategy_desc, genfs_badop },		/* strategy */
    747 	{ &vop_print_desc, fifo_print },		/* print */
    748 	{ &vop_islocked_desc, genfs_islocked },		/* islocked */
    749 	{ &vop_pathconf_desc, fifo_pathconf },		/* pathconf */
    750 	{ &vop_advlock_desc, genfs_einval },		/* advlock */
    751 	{ &vop_bwrite_desc, genfs_nullop },		/* bwrite */
    752 	{ &vop_putpages_desc, genfs_null_putpages },	/* putpages */
    753 	{ NULL, NULL }
    754 };
    755 const struct vnodeopv_desc fifo_vnodeop_opv_desc =
    756 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
    757