1/*-
2 * Copyright (c) 1990, 1993, 1995
3 *	The Regents of the University of California.
4 * Copyright (c) 2005 Robert N. M. Watson
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 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	@(#)fifo_vnops.c	8.10 (Berkeley) 5/27/95
32 * $FreeBSD$
33 */
34
35#include <sys/param.h>
36#include <sys/event.h>
37#include <sys/file.h>
38#include <sys/filedesc.h>
39#include <sys/filio.h>
40#include <sys/fcntl.h>
41#include <sys/kernel.h>
42#include <sys/lock.h>
43#include <sys/mutex.h>
44#include <sys/malloc.h>
45#include <sys/poll.h>
46#include <sys/proc.h>
47#include <sys/signalvar.h>
48#include <sys/socket.h>
49#include <sys/socketvar.h>
50#include <sys/sx.h>
51#include <sys/systm.h>
52#include <sys/un.h>
53#include <sys/unistd.h>
54#include <sys/vnode.h>
55#include <fs/fifofs/fifo.h>
56
57static fo_rdwr_t        fifo_read_f;
58static fo_rdwr_t        fifo_write_f;
59static fo_ioctl_t       fifo_ioctl_f;
60static fo_poll_t        fifo_poll_f;
61static fo_kqfilter_t    fifo_kqfilter_f;
62static fo_stat_t        fifo_stat_f;
63static fo_close_t       fifo_close_f;
64static fo_truncate_t    fifo_truncate_f;
65
66struct fileops fifo_ops_f = {
67	.fo_read =      fifo_read_f,
68	.fo_write =     fifo_write_f,
69	.fo_truncate =  fifo_truncate_f,
70	.fo_ioctl =     fifo_ioctl_f,
71	.fo_poll =      fifo_poll_f,
72	.fo_kqfilter =  fifo_kqfilter_f,
73	.fo_stat =      fifo_stat_f,
74	.fo_close =     fifo_close_f,
75	.fo_chmod =	vn_chmod,
76	.fo_chown =	vn_chown,
77	.fo_flags =     DFLAG_PASSABLE
78};
79
80/*
81 * This structure is associated with the FIFO vnode and stores
82 * the state associated with the FIFO.
83 * Notes about locking:
84 *   - fi_readsock and fi_writesock are invariant since init time.
85 *   - fi_readers and fi_writers are vnode lock protected.
86 *   - fi_wgen is fif_mtx lock protected.
87 */
88struct fifoinfo {
89	struct socket	*fi_readsock;
90	struct socket	*fi_writesock;
91	long		fi_readers;
92	long		fi_writers;
93	int		fi_wgen;
94};
95
96static vop_print_t	fifo_print;
97static vop_open_t	fifo_open;
98static vop_close_t	fifo_close;
99static vop_pathconf_t	fifo_pathconf;
100static vop_advlock_t	fifo_advlock;
101
102static void	filt_fifordetach(struct knote *kn);
103static int	filt_fiforead(struct knote *kn, long hint);
104static void	filt_fifowdetach(struct knote *kn);
105static int	filt_fifowrite(struct knote *kn, long hint);
106static void	filt_fifodetach_notsup(struct knote *kn);
107static int	filt_fifo_notsup(struct knote *kn, long hint);
108
109static struct filterops fiforead_filtops = {
110	.f_isfd = 1,
111	.f_detach = filt_fifordetach,
112	.f_event = filt_fiforead,
113};
114static struct filterops fifowrite_filtops = {
115	.f_isfd = 1,
116	.f_detach = filt_fifowdetach,
117	.f_event = filt_fifowrite,
118};
119static struct filterops fifo_notsup_filtops = {
120	.f_isfd = 1,
121	.f_detach = filt_fifodetach_notsup,
122	.f_event = filt_fifo_notsup,
123};
124
125struct vop_vector fifo_specops = {
126	.vop_default =		&default_vnodeops,
127
128	.vop_advlock =		fifo_advlock,
129	.vop_close =		fifo_close,
130	.vop_create =		VOP_PANIC,
131	.vop_getattr =		VOP_EBADF,
132	.vop_ioctl =		VOP_PANIC,
133	.vop_kqfilter =		VOP_PANIC,
134	.vop_link =		VOP_PANIC,
135	.vop_mkdir =		VOP_PANIC,
136	.vop_mknod =		VOP_PANIC,
137	.vop_open =		fifo_open,
138	.vop_pathconf =		fifo_pathconf,
139	.vop_print =		fifo_print,
140	.vop_read =		VOP_PANIC,
141	.vop_readdir =		VOP_PANIC,
142	.vop_readlink =		VOP_PANIC,
143	.vop_reallocblks =	VOP_PANIC,
144	.vop_reclaim =		VOP_NULL,
145	.vop_remove =		VOP_PANIC,
146	.vop_rename =		VOP_PANIC,
147	.vop_rmdir =		VOP_PANIC,
148	.vop_setattr =		VOP_EBADF,
149	.vop_symlink =		VOP_PANIC,
150	.vop_write =		VOP_PANIC,
151};
152
153struct mtx fifo_mtx;
154MTX_SYSINIT(fifo, &fifo_mtx, "fifo mutex", MTX_DEF);
155
156/*
157 * Dispose of fifo resources.
158 */
159static void
160fifo_cleanup(struct vnode *vp)
161{
162	struct fifoinfo *fip = vp->v_fifoinfo;
163
164	ASSERT_VOP_ELOCKED(vp, "fifo_cleanup");
165	if (fip->fi_readers == 0 && fip->fi_writers == 0) {
166		vp->v_fifoinfo = NULL;
167		(void)soclose(fip->fi_readsock);
168		(void)soclose(fip->fi_writesock);
169		free(fip, M_VNODE);
170	}
171}
172
173/*
174 * Open called to set up a new instance of a fifo or
175 * to find an active instance of a fifo.
176 */
177/* ARGSUSED */
178static int
179fifo_open(ap)
180	struct vop_open_args /* {
181		struct vnode *a_vp;
182		int  a_mode;
183		struct ucred *a_cred;
184		struct thread *a_td;
185		struct file *a_fp;
186	} */ *ap;
187{
188	struct vnode *vp = ap->a_vp;
189	struct fifoinfo *fip;
190	struct thread *td = ap->a_td;
191	struct ucred *cred = ap->a_cred;
192	struct file *fp = ap->a_fp;
193	struct socket *rso, *wso;
194	int error;
195
196	ASSERT_VOP_ELOCKED(vp, "fifo_open");
197	if (fp == NULL || (ap->a_mode & FEXEC) != 0)
198		return (EINVAL);
199	if ((fip = vp->v_fifoinfo) == NULL) {
200		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
201		error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, cred, td);
202		if (error)
203			goto fail1;
204		fip->fi_readsock = rso;
205		error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, cred, td);
206		if (error)
207			goto fail2;
208		fip->fi_writesock = wso;
209		error = soconnect2(wso, rso);
210		/* Close the direction we do not use, so we can get POLLHUP. */
211		if (error == 0)
212			error = soshutdown(rso, SHUT_WR);
213		if (error) {
214			(void)soclose(wso);
215fail2:
216			(void)soclose(rso);
217fail1:
218			free(fip, M_VNODE);
219			return (error);
220		}
221		fip->fi_wgen = fip->fi_readers = fip->fi_writers = 0;
222		wso->so_snd.sb_lowat = PIPE_BUF;
223		SOCKBUF_LOCK(&rso->so_rcv);
224		rso->so_rcv.sb_state |= SBS_CANTRCVMORE;
225		SOCKBUF_UNLOCK(&rso->so_rcv);
226		KASSERT(vp->v_fifoinfo == NULL,
227		    ("fifo_open: v_fifoinfo race"));
228		vp->v_fifoinfo = fip;
229	}
230
231	/*
232	 * Use the fifo_mtx lock here, in addition to the vnode lock,
233	 * in order to allow vnode lock dropping before msleep() calls
234	 * and still avoiding missed wakeups.
235	 */
236	mtx_lock(&fifo_mtx);
237	if (ap->a_mode & FREAD) {
238		fip->fi_readers++;
239		if (fip->fi_readers == 1) {
240			SOCKBUF_LOCK(&fip->fi_writesock->so_snd);
241			fip->fi_writesock->so_snd.sb_state &= ~SBS_CANTSENDMORE;
242			SOCKBUF_UNLOCK(&fip->fi_writesock->so_snd);
243			if (fip->fi_writers > 0) {
244				wakeup(&fip->fi_writers);
245				sowwakeup(fip->fi_writesock);
246			}
247		}
248		fp->f_seqcount = fip->fi_wgen - fip->fi_writers;
249	}
250	if (ap->a_mode & FWRITE) {
251		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
252			mtx_unlock(&fifo_mtx);
253			if (fip->fi_writers == 0)
254				fifo_cleanup(vp);
255			return (ENXIO);
256		}
257		fip->fi_writers++;
258		if (fip->fi_writers == 1) {
259			SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
260			fip->fi_readsock->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
261			SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
262			if (fip->fi_readers > 0) {
263				wakeup(&fip->fi_readers);
264				sorwakeup(fip->fi_readsock);
265			}
266		}
267	}
268	if ((ap->a_mode & O_NONBLOCK) == 0) {
269		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
270			VOP_UNLOCK(vp, 0);
271			error = msleep(&fip->fi_readers, &fifo_mtx,
272			    PDROP | PCATCH | PSOCK, "fifoor", 0);
273			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
274			if (error) {
275				fip->fi_readers--;
276				if (fip->fi_readers == 0) {
277					socantsendmore(fip->fi_writesock);
278					fifo_cleanup(vp);
279				}
280				return (error);
281			}
282			mtx_lock(&fifo_mtx);
283			/*
284			 * We must have got woken up because we had a writer.
285			 * That (and not still having one) is the condition
286			 * that we must wait for.
287			 */
288		}
289		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
290			VOP_UNLOCK(vp, 0);
291			error = msleep(&fip->fi_writers, &fifo_mtx,
292			    PDROP | PCATCH | PSOCK, "fifoow", 0);
293			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
294			if (error) {
295				fip->fi_writers--;
296				if (fip->fi_writers == 0) {
297					mtx_lock(&fifo_mtx);
298					fip->fi_wgen++;
299					mtx_unlock(&fifo_mtx);
300					socantrcvmore(fip->fi_readsock);
301					fifo_cleanup(vp);
302				}
303				return (error);
304			}
305			/*
306			 * We must have got woken up because we had
307			 * a reader.  That (and not still having one)
308			 * is the condition that we must wait for.
309			 */
310			mtx_lock(&fifo_mtx);
311		}
312	}
313	mtx_unlock(&fifo_mtx);
314	KASSERT(fp != NULL, ("can't fifo/vnode bypass"));
315	KASSERT(fp->f_ops == &badfileops, ("not badfileops in fifo_open"));
316	finit(fp, fp->f_flag, DTYPE_FIFO, fip, &fifo_ops_f);
317	return (0);
318}
319
320static void
321filt_fifordetach(struct knote *kn)
322{
323	struct socket *so = (struct socket *)kn->kn_hook;
324
325	SOCKBUF_LOCK(&so->so_rcv);
326	knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1);
327	if (knlist_empty(&so->so_rcv.sb_sel.si_note))
328		so->so_rcv.sb_flags &= ~SB_KNOTE;
329	SOCKBUF_UNLOCK(&so->so_rcv);
330}
331
332static int
333filt_fiforead(struct knote *kn, long hint)
334{
335	struct socket *so = (struct socket *)kn->kn_hook;
336
337	SOCKBUF_LOCK_ASSERT(&so->so_rcv);
338	kn->kn_data = so->so_rcv.sb_cc;
339	if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
340		kn->kn_flags |= EV_EOF;
341		return (1);
342	} else {
343		kn->kn_flags &= ~EV_EOF;
344		return (kn->kn_data > 0);
345	}
346}
347
348static void
349filt_fifowdetach(struct knote *kn)
350{
351	struct socket *so = (struct socket *)kn->kn_hook;
352
353	SOCKBUF_LOCK(&so->so_snd);
354	knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1);
355	if (knlist_empty(&so->so_snd.sb_sel.si_note))
356		so->so_snd.sb_flags &= ~SB_KNOTE;
357	SOCKBUF_UNLOCK(&so->so_snd);
358}
359
360static int
361filt_fifowrite(struct knote *kn, long hint)
362{
363	struct socket *so = (struct socket *)kn->kn_hook;
364
365	SOCKBUF_LOCK_ASSERT(&so->so_snd);
366	kn->kn_data = sbspace(&so->so_snd);
367	if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
368		kn->kn_flags |= EV_EOF;
369		return (1);
370	} else {
371		kn->kn_flags &= ~EV_EOF;
372	        return (kn->kn_data >= so->so_snd.sb_lowat);
373	}
374}
375
376static void
377filt_fifodetach_notsup(struct knote *kn)
378{
379
380}
381
382static int
383filt_fifo_notsup(struct knote *kn, long hint)
384{
385
386	return (0);
387}
388
389/*
390 * Device close routine
391 */
392/* ARGSUSED */
393static int
394fifo_close(ap)
395	struct vop_close_args /* {
396		struct vnode *a_vp;
397		int  a_fflag;
398		struct ucred *a_cred;
399		struct thread *a_td;
400	} */ *ap;
401{
402	struct vnode *vp = ap->a_vp;
403	struct fifoinfo *fip = vp->v_fifoinfo;
404
405	ASSERT_VOP_ELOCKED(vp, "fifo_close");
406	if (fip == NULL) {
407		printf("fifo_close: no v_fifoinfo %p\n", vp);
408		return (0);
409	}
410	if (ap->a_fflag & FREAD) {
411		fip->fi_readers--;
412		if (fip->fi_readers == 0)
413			socantsendmore(fip->fi_writesock);
414	}
415	if (ap->a_fflag & FWRITE) {
416		fip->fi_writers--;
417		if (fip->fi_writers == 0) {
418			mtx_lock(&fifo_mtx);
419			fip->fi_wgen++;
420			mtx_unlock(&fifo_mtx);
421			socantrcvmore(fip->fi_readsock);
422		}
423	}
424	fifo_cleanup(vp);
425	return (0);
426}
427
428/*
429 * Print out internal contents of a fifo vnode.
430 */
431int
432fifo_printinfo(vp)
433	struct vnode *vp;
434{
435	register struct fifoinfo *fip = vp->v_fifoinfo;
436
437	if (fip == NULL){
438		printf(", NULL v_fifoinfo");
439		return (0);
440	}
441	printf(", fifo with %ld readers and %ld writers",
442		fip->fi_readers, fip->fi_writers);
443	return (0);
444}
445
446/*
447 * Print out the contents of a fifo vnode.
448 */
449static int
450fifo_print(ap)
451	struct vop_print_args /* {
452		struct vnode *a_vp;
453	} */ *ap;
454{
455	printf("    ");
456	fifo_printinfo(ap->a_vp);
457	printf("\n");
458	return (0);
459}
460
461/*
462 * Return POSIX pathconf information applicable to fifo's.
463 */
464static int
465fifo_pathconf(ap)
466	struct vop_pathconf_args /* {
467		struct vnode *a_vp;
468		int a_name;
469		int *a_retval;
470	} */ *ap;
471{
472
473	switch (ap->a_name) {
474	case _PC_LINK_MAX:
475		*ap->a_retval = LINK_MAX;
476		return (0);
477	case _PC_PIPE_BUF:
478		*ap->a_retval = PIPE_BUF;
479		return (0);
480	case _PC_CHOWN_RESTRICTED:
481		*ap->a_retval = 1;
482		return (0);
483	default:
484		return (EINVAL);
485	}
486	/* NOTREACHED */
487}
488
489/*
490 * Fifo advisory byte-level locks.
491 */
492/* ARGSUSED */
493static int
494fifo_advlock(ap)
495	struct vop_advlock_args /* {
496		struct vnode *a_vp;
497		caddr_t  a_id;
498		int  a_op;
499		struct flock *a_fl;
500		int  a_flags;
501	} */ *ap;
502{
503
504	return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
505}
506
507static int
508fifo_close_f(struct file *fp, struct thread *td)
509{
510
511	return (vnops.fo_close(fp, td));
512}
513
514/*
515 * The implementation of ioctl() for named fifos is complicated by the fact
516 * that we permit O_RDWR fifo file descriptors, meaning that the actions of
517 * ioctls may have to be applied to both the underlying sockets rather than
518 * just one.  The original implementation simply forward the ioctl to one
519 * or both sockets based on fp->f_flag.  We now consider each ioctl
520 * separately, as the composition effect requires careful ordering.
521 *
522 * We do not blindly pass all ioctls through to the socket in order to avoid
523 * providing unnecessary ioctls that might be improperly depended on by
524 * applications (such as socket-specific, routing, and interface ioctls).
525 *
526 * Unlike sys_pipe.c, fifos do not implement the deprecated TIOCSPGRP and
527 * TIOCGPGRP ioctls.  Earlier implementations of fifos did forward SIOCSPGRP
528 * and SIOCGPGRP ioctls, so we might need to re-add those here.
529 */
530static int
531fifo_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred,
532    struct thread *td)
533{
534	struct fifoinfo *fi;
535	struct file filetmp;	/* Local, so need not be locked. */
536	int error;
537
538	error = ENOTTY;
539	fi = fp->f_data;
540
541	switch (com) {
542	case FIONBIO:
543		/*
544		 * Non-blocking I/O is implemented at the fifo layer using
545		 * MSG_NBIO, so does not need to be forwarded down the stack.
546		 */
547		return (0);
548
549	case FIOASYNC:
550	case FIOSETOWN:
551	case FIOGETOWN:
552		/*
553		 * These socket ioctls don't have any ordering requirements,
554		 * so are called in an arbitrary order, and only on the
555		 * sockets indicated by the file descriptor rights.
556		 *
557		 * XXXRW: If O_RDWR and the read socket accepts an ioctl but
558		 * the write socket doesn't, the socketpair is left in an
559		 * inconsistent state.
560		 */
561		if (fp->f_flag & FREAD) {
562			filetmp.f_data = fi->fi_readsock;
563			filetmp.f_cred = cred;
564			error = soo_ioctl(&filetmp, com, data, cred, td);
565			if (error)
566				return (error);
567		}
568		if (fp->f_flag & FWRITE) {
569			filetmp.f_data = fi->fi_writesock;
570			filetmp.f_cred = cred;
571			error = soo_ioctl(&filetmp, com, data, cred, td);
572		}
573		return (error);
574
575	case FIONREAD:
576		/*
577		 * FIONREAD will return 0 for non-readable descriptors, and
578		 * the results of FIONREAD on the read socket for readable
579		 * descriptors.
580		 */
581		if (!(fp->f_flag & FREAD)) {
582			*(int *)data = 0;
583			return (0);
584		}
585		filetmp.f_data = fi->fi_readsock;
586		filetmp.f_cred = cred;
587		return (soo_ioctl(&filetmp, com, data, cred, td));
588
589	default:
590		return (ENOTTY);
591	}
592}
593
594/*
595 * Because fifos are now a file descriptor layer object, EVFILT_VNODE is not
596 * implemented.  Likely, fifo_kqfilter() should be removed, and
597 * fifo_kqfilter_f() should know how to forward the request to the underling
598 * vnode using f_vnode in the file descriptor here.
599 */
600static int
601fifo_kqfilter_f(struct file *fp, struct knote *kn)
602{
603	struct fifoinfo *fi;
604	struct socket *so;
605	struct sockbuf *sb;
606
607	fi = fp->f_data;
608
609	/*
610	 * If a filter is requested that is not supported by this file
611	 * descriptor, don't return an error, but also don't ever generate an
612	 * event.
613	 */
614	if ((kn->kn_filter == EVFILT_READ) && !(fp->f_flag & FREAD)) {
615		kn->kn_fop = &fifo_notsup_filtops;
616		return (0);
617	}
618
619	if ((kn->kn_filter == EVFILT_WRITE) && !(fp->f_flag & FWRITE)) {
620		kn->kn_fop = &fifo_notsup_filtops;
621		return (0);
622	}
623
624	switch (kn->kn_filter) {
625	case EVFILT_READ:
626		kn->kn_fop = &fiforead_filtops;
627		so = fi->fi_readsock;
628		sb = &so->so_rcv;
629		break;
630	case EVFILT_WRITE:
631		kn->kn_fop = &fifowrite_filtops;
632		so = fi->fi_writesock;
633		sb = &so->so_snd;
634		break;
635	default:
636		return (EINVAL);
637	}
638
639	kn->kn_hook = (caddr_t)so;
640
641	SOCKBUF_LOCK(sb);
642	knlist_add(&sb->sb_sel.si_note, kn, 1);
643	sb->sb_flags |= SB_KNOTE;
644	SOCKBUF_UNLOCK(sb);
645
646	return (0);
647}
648
649static int
650fifo_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
651{
652	struct fifoinfo *fip;
653	struct file filetmp;
654	int levents, revents = 0;
655
656	fip = fp->f_data;
657	levents = events &
658	    (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND);
659	if ((fp->f_flag & FREAD) && levents) {
660		filetmp.f_data = fip->fi_readsock;
661		filetmp.f_cred = cred;
662		mtx_lock(&fifo_mtx);
663		if (fp->f_seqcount == fip->fi_wgen)
664			levents |= POLLINIGNEOF;
665		mtx_unlock(&fifo_mtx);
666		revents |= soo_poll(&filetmp, levents, cred, td);
667	}
668	levents = events & (POLLOUT | POLLWRNORM | POLLWRBAND);
669	if ((fp->f_flag & FWRITE) && levents) {
670		filetmp.f_data = fip->fi_writesock;
671		filetmp.f_cred = cred;
672		revents |= soo_poll(&filetmp, levents, cred, td);
673	}
674	return (revents);
675}
676
677static int
678fifo_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
679{
680	struct fifoinfo *fip;
681	int sflags;
682
683	fip = fp->f_data;
684	KASSERT(uio->uio_rw == UIO_READ,("fifo_read mode"));
685	if (uio->uio_resid == 0)
686		return (0);
687	sflags = (fp->f_flag & FNONBLOCK) ? MSG_NBIO : 0;
688	return (soreceive(fip->fi_readsock, NULL, uio, NULL, NULL, &sflags));
689}
690
691static int
692fifo_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
693{
694
695	return (vnops.fo_stat(fp, sb, cred, td));
696}
697
698static int
699fifo_truncate_f(struct file *fp, off_t length, struct ucred *cred, struct thread *td)
700{
701
702	return (vnops.fo_truncate(fp, length, cred, td));
703}
704
705static int
706fifo_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
707{
708	struct fifoinfo *fip;
709	int sflags;
710
711	fip = fp->f_data;
712	KASSERT(uio->uio_rw == UIO_WRITE,("fifo_write mode"));
713	sflags = (fp->f_flag & FNONBLOCK) ? MSG_NBIO : 0;
714	return (sosend(fip->fi_writesock, NULL, uio, 0, NULL, sflags, td));
715}
716