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