Deleted Added
full compact
fifo_vnops.c (87725) fifo_vnops.c (88739)
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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
34 * $FreeBSD: head/sys/fs/fifofs/fifo_vnops.c 87725 2001-12-12 09:35:33Z alfred $
34 * $FreeBSD: head/sys/fs/fifofs/fifo_vnops.c 88739 2001-12-31 17:45:16Z rwatson $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/unistd.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/vnode.h>
44#include <sys/proc.h> /* XXXKSE */
45#include <sys/socket.h>
46#include <sys/socketvar.h>
47#include <sys/filio.h>
48#include <sys/fcntl.h>
49#include <sys/file.h>
50#include <sys/event.h>
51#include <sys/poll.h>
52#include <sys/un.h>
53#include <fs/fifofs/fifo.h>
54
55/*
56 * This structure is associated with the FIFO vnode and stores
57 * the state associated with the FIFO.
58 */
59struct fifoinfo {
60 struct socket *fi_readsock;
61 struct socket *fi_writesock;
62 long fi_readers;
63 long fi_writers;
64};
65
66static int fifo_badop __P((void));
67static int fifo_print __P((struct vop_print_args *));
68static int fifo_lookup __P((struct vop_lookup_args *));
69static int fifo_open __P((struct vop_open_args *));
70static int fifo_close __P((struct vop_close_args *));
71static int fifo_read __P((struct vop_read_args *));
72static int fifo_write __P((struct vop_write_args *));
73static int fifo_ioctl __P((struct vop_ioctl_args *));
74static int fifo_poll __P((struct vop_poll_args *));
75static int fifo_kqfilter __P((struct vop_kqfilter_args *));
76static int fifo_pathconf __P((struct vop_pathconf_args *));
77static int fifo_advlock __P((struct vop_advlock_args *));
78
79static void filt_fifordetach(struct knote *kn);
80static int filt_fiforead(struct knote *kn, long hint);
81static void filt_fifowdetach(struct knote *kn);
82static int filt_fifowrite(struct knote *kn, long hint);
83
84static struct filterops fiforead_filtops =
85 { 1, NULL, filt_fifordetach, filt_fiforead };
86static struct filterops fifowrite_filtops =
87 { 1, NULL, filt_fifowdetach, filt_fifowrite };
88
89vop_t **fifo_vnodeop_p;
90static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
91 { &vop_default_desc, (vop_t *) vop_defaultop },
92 { &vop_access_desc, (vop_t *) vop_ebadf },
93 { &vop_advlock_desc, (vop_t *) fifo_advlock },
94 { &vop_close_desc, (vop_t *) fifo_close },
95 { &vop_create_desc, (vop_t *) fifo_badop },
96 { &vop_getattr_desc, (vop_t *) vop_ebadf },
97 { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
98 { &vop_ioctl_desc, (vop_t *) fifo_ioctl },
99 { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter },
100 { &vop_lease_desc, (vop_t *) vop_null },
101 { &vop_link_desc, (vop_t *) fifo_badop },
102 { &vop_lookup_desc, (vop_t *) fifo_lookup },
103 { &vop_mkdir_desc, (vop_t *) fifo_badop },
104 { &vop_mknod_desc, (vop_t *) fifo_badop },
105 { &vop_open_desc, (vop_t *) fifo_open },
106 { &vop_pathconf_desc, (vop_t *) fifo_pathconf },
107 { &vop_poll_desc, (vop_t *) fifo_poll },
108 { &vop_print_desc, (vop_t *) fifo_print },
109 { &vop_read_desc, (vop_t *) fifo_read },
110 { &vop_readdir_desc, (vop_t *) fifo_badop },
111 { &vop_readlink_desc, (vop_t *) fifo_badop },
112 { &vop_reallocblks_desc, (vop_t *) fifo_badop },
113 { &vop_reclaim_desc, (vop_t *) vop_null },
114 { &vop_remove_desc, (vop_t *) fifo_badop },
115 { &vop_rename_desc, (vop_t *) fifo_badop },
116 { &vop_rmdir_desc, (vop_t *) fifo_badop },
117 { &vop_setattr_desc, (vop_t *) vop_ebadf },
118 { &vop_symlink_desc, (vop_t *) fifo_badop },
119 { &vop_write_desc, (vop_t *) fifo_write },
120 { NULL, NULL }
121};
122static struct vnodeopv_desc fifo_vnodeop_opv_desc =
123 { &fifo_vnodeop_p, fifo_vnodeop_entries };
124
125VNODEOP_SET(fifo_vnodeop_opv_desc);
126
127int
128fifo_vnoperate(ap)
129 struct vop_generic_args /* {
130 struct vnodeop_desc *a_desc;
131 <other random data follows, presumably>
132 } */ *ap;
133{
134 return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
135}
136
137/*
138 * Trivial lookup routine that always fails.
139 */
140/* ARGSUSED */
141static int
142fifo_lookup(ap)
143 struct vop_lookup_args /* {
144 struct vnode * a_dvp;
145 struct vnode ** a_vpp;
146 struct componentname * a_cnp;
147 } */ *ap;
148{
149
150 *ap->a_vpp = NULL;
151 return (ENOTDIR);
152}
153
154/*
155 * Open called to set up a new instance of a fifo or
156 * to find an active instance of a fifo.
157 */
158/* ARGSUSED */
159static int
160fifo_open(ap)
161 struct vop_open_args /* {
162 struct vnode *a_vp;
163 int a_mode;
164 struct ucred *a_cred;
165 struct thread *a_td;
166 } */ *ap;
167{
168 struct vnode *vp = ap->a_vp;
169 struct fifoinfo *fip;
170 struct thread *td = ap->a_td;
171 struct socket *rso, *wso;
172 int error;
173
174 if ((fip = vp->v_fifoinfo) == NULL) {
175 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
176 vp->v_fifoinfo = fip;
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/unistd.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/vnode.h>
44#include <sys/proc.h> /* XXXKSE */
45#include <sys/socket.h>
46#include <sys/socketvar.h>
47#include <sys/filio.h>
48#include <sys/fcntl.h>
49#include <sys/file.h>
50#include <sys/event.h>
51#include <sys/poll.h>
52#include <sys/un.h>
53#include <fs/fifofs/fifo.h>
54
55/*
56 * This structure is associated with the FIFO vnode and stores
57 * the state associated with the FIFO.
58 */
59struct fifoinfo {
60 struct socket *fi_readsock;
61 struct socket *fi_writesock;
62 long fi_readers;
63 long fi_writers;
64};
65
66static int fifo_badop __P((void));
67static int fifo_print __P((struct vop_print_args *));
68static int fifo_lookup __P((struct vop_lookup_args *));
69static int fifo_open __P((struct vop_open_args *));
70static int fifo_close __P((struct vop_close_args *));
71static int fifo_read __P((struct vop_read_args *));
72static int fifo_write __P((struct vop_write_args *));
73static int fifo_ioctl __P((struct vop_ioctl_args *));
74static int fifo_poll __P((struct vop_poll_args *));
75static int fifo_kqfilter __P((struct vop_kqfilter_args *));
76static int fifo_pathconf __P((struct vop_pathconf_args *));
77static int fifo_advlock __P((struct vop_advlock_args *));
78
79static void filt_fifordetach(struct knote *kn);
80static int filt_fiforead(struct knote *kn, long hint);
81static void filt_fifowdetach(struct knote *kn);
82static int filt_fifowrite(struct knote *kn, long hint);
83
84static struct filterops fiforead_filtops =
85 { 1, NULL, filt_fifordetach, filt_fiforead };
86static struct filterops fifowrite_filtops =
87 { 1, NULL, filt_fifowdetach, filt_fifowrite };
88
89vop_t **fifo_vnodeop_p;
90static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
91 { &vop_default_desc, (vop_t *) vop_defaultop },
92 { &vop_access_desc, (vop_t *) vop_ebadf },
93 { &vop_advlock_desc, (vop_t *) fifo_advlock },
94 { &vop_close_desc, (vop_t *) fifo_close },
95 { &vop_create_desc, (vop_t *) fifo_badop },
96 { &vop_getattr_desc, (vop_t *) vop_ebadf },
97 { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
98 { &vop_ioctl_desc, (vop_t *) fifo_ioctl },
99 { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter },
100 { &vop_lease_desc, (vop_t *) vop_null },
101 { &vop_link_desc, (vop_t *) fifo_badop },
102 { &vop_lookup_desc, (vop_t *) fifo_lookup },
103 { &vop_mkdir_desc, (vop_t *) fifo_badop },
104 { &vop_mknod_desc, (vop_t *) fifo_badop },
105 { &vop_open_desc, (vop_t *) fifo_open },
106 { &vop_pathconf_desc, (vop_t *) fifo_pathconf },
107 { &vop_poll_desc, (vop_t *) fifo_poll },
108 { &vop_print_desc, (vop_t *) fifo_print },
109 { &vop_read_desc, (vop_t *) fifo_read },
110 { &vop_readdir_desc, (vop_t *) fifo_badop },
111 { &vop_readlink_desc, (vop_t *) fifo_badop },
112 { &vop_reallocblks_desc, (vop_t *) fifo_badop },
113 { &vop_reclaim_desc, (vop_t *) vop_null },
114 { &vop_remove_desc, (vop_t *) fifo_badop },
115 { &vop_rename_desc, (vop_t *) fifo_badop },
116 { &vop_rmdir_desc, (vop_t *) fifo_badop },
117 { &vop_setattr_desc, (vop_t *) vop_ebadf },
118 { &vop_symlink_desc, (vop_t *) fifo_badop },
119 { &vop_write_desc, (vop_t *) fifo_write },
120 { NULL, NULL }
121};
122static struct vnodeopv_desc fifo_vnodeop_opv_desc =
123 { &fifo_vnodeop_p, fifo_vnodeop_entries };
124
125VNODEOP_SET(fifo_vnodeop_opv_desc);
126
127int
128fifo_vnoperate(ap)
129 struct vop_generic_args /* {
130 struct vnodeop_desc *a_desc;
131 <other random data follows, presumably>
132 } */ *ap;
133{
134 return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
135}
136
137/*
138 * Trivial lookup routine that always fails.
139 */
140/* ARGSUSED */
141static int
142fifo_lookup(ap)
143 struct vop_lookup_args /* {
144 struct vnode * a_dvp;
145 struct vnode ** a_vpp;
146 struct componentname * a_cnp;
147 } */ *ap;
148{
149
150 *ap->a_vpp = NULL;
151 return (ENOTDIR);
152}
153
154/*
155 * Open called to set up a new instance of a fifo or
156 * to find an active instance of a fifo.
157 */
158/* ARGSUSED */
159static int
160fifo_open(ap)
161 struct vop_open_args /* {
162 struct vnode *a_vp;
163 int a_mode;
164 struct ucred *a_cred;
165 struct thread *a_td;
166 } */ *ap;
167{
168 struct vnode *vp = ap->a_vp;
169 struct fifoinfo *fip;
170 struct thread *td = ap->a_td;
171 struct socket *rso, *wso;
172 int error;
173
174 if ((fip = vp->v_fifoinfo) == NULL) {
175 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
176 vp->v_fifoinfo = fip;
177 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_td);
177 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0,
178 ap->a_td->td_proc->p_ucred, ap->a_td);
178 if (error) {
179 free(fip, M_VNODE);
180 vp->v_fifoinfo = NULL;
181 return (error);
182 }
183 fip->fi_readsock = rso;
179 if (error) {
180 free(fip, M_VNODE);
181 vp->v_fifoinfo = NULL;
182 return (error);
183 }
184 fip->fi_readsock = rso;
184 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_td);
185 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0,
186 ap->a_td->td_proc->p_ucred, ap->a_td);
185 if (error) {
186 (void)soclose(rso);
187 free(fip, M_VNODE);
188 vp->v_fifoinfo = NULL;
189 return (error);
190 }
191 fip->fi_writesock = wso;
192 error = unp_connect2(wso, rso);
193 if (error) {
194 (void)soclose(wso);
195 (void)soclose(rso);
196 free(fip, M_VNODE);
197 vp->v_fifoinfo = NULL;
198 return (error);
199 }
200 fip->fi_readers = fip->fi_writers = 0;
201 wso->so_snd.sb_lowat = PIPE_BUF;
202 }
203 if (ap->a_mode & FREAD) {
204 fip->fi_readers++;
205 if (fip->fi_readers == 1) {
206 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
207 if (fip->fi_writers > 0) {
208 wakeup((caddr_t)&fip->fi_writers);
209 sowwakeup(fip->fi_writesock);
210 }
211 }
212 }
213 if (ap->a_mode & FWRITE) {
214 fip->fi_writers++;
215 if (fip->fi_writers == 1) {
216 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
217 if (fip->fi_readers > 0) {
218 wakeup((caddr_t)&fip->fi_readers);
219 sorwakeup(fip->fi_writesock);
220 }
221 }
222 }
223 if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
224 while (fip->fi_writers == 0) {
225 VOP_UNLOCK(vp, 0, td);
226 error = tsleep((caddr_t)&fip->fi_readers,
227 PCATCH | PSOCK, "fifoor", 0);
228 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
229 if (error)
230 goto bad;
231 }
232 }
233 if (ap->a_mode & FWRITE) {
234 if (ap->a_mode & O_NONBLOCK) {
235 if (fip->fi_readers == 0) {
236 error = ENXIO;
237 goto bad;
238 }
239 } else {
240 while (fip->fi_readers == 0) {
241 VOP_UNLOCK(vp, 0, td);
242 error = tsleep((caddr_t)&fip->fi_writers,
243 PCATCH | PSOCK, "fifoow", 0);
244 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
245 if (error)
246 goto bad;
247 }
248 }
249 }
250 return (0);
251bad:
252 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, td);
253 return (error);
254}
255
256/*
257 * Vnode op for read
258 */
259/* ARGSUSED */
260static int
261fifo_read(ap)
262 struct vop_read_args /* {
263 struct vnode *a_vp;
264 struct uio *a_uio;
265 int a_ioflag;
266 struct ucred *a_cred;
267 } */ *ap;
268{
269 struct uio *uio = ap->a_uio;
270 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
271 struct thread *td = uio->uio_td;
272 int error, startresid;
273
274#ifdef DIAGNOSTIC
275 if (uio->uio_rw != UIO_READ)
276 panic("fifo_read mode");
277#endif
278 if (uio->uio_resid == 0)
279 return (0);
280 if (ap->a_ioflag & IO_NDELAY)
281 rso->so_state |= SS_NBIO;
282 startresid = uio->uio_resid;
283 VOP_UNLOCK(ap->a_vp, 0, td);
284 error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
285 (struct mbuf **)0, (int *)0);
286 /*
287 * Clear EOF indication after first such return.
288 */
289 if (uio->uio_resid == startresid)
290 rso->so_state &= ~SS_CANTRCVMORE;
291 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
292 if (ap->a_ioflag & IO_NDELAY)
293 rso->so_state &= ~SS_NBIO;
294 return (error);
295}
296
297/*
298 * Vnode op for write
299 */
300/* ARGSUSED */
301static int
302fifo_write(ap)
303 struct vop_write_args /* {
304 struct vnode *a_vp;
305 struct uio *a_uio;
306 int a_ioflag;
307 struct ucred *a_cred;
308 } */ *ap;
309{
310 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
311 struct thread *td = ap->a_uio->uio_td;
312 int error;
313
314#ifdef DIAGNOSTIC
315 if (ap->a_uio->uio_rw != UIO_WRITE)
316 panic("fifo_write mode");
317#endif
318 if (ap->a_ioflag & IO_NDELAY)
319 wso->so_state |= SS_NBIO;
320 VOP_UNLOCK(ap->a_vp, 0, td);
321 error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
322 (struct mbuf *)0, 0, td);
323 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
324 if (ap->a_ioflag & IO_NDELAY)
325 wso->so_state &= ~SS_NBIO;
326 return (error);
327}
328
329/*
330 * Device ioctl operation.
331 */
332/* ARGSUSED */
333static int
334fifo_ioctl(ap)
335 struct vop_ioctl_args /* {
336 struct vnode *a_vp;
337 int a_command;
338 caddr_t a_data;
339 int a_fflag;
340 struct ucred *a_cred;
341 struct thread *a_td;
342 } */ *ap;
343{
344 struct file filetmp;
345 int error;
346
347 if (ap->a_command == FIONBIO)
348 return (0);
349 if (ap->a_fflag & FREAD) {
350 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
351 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_td);
352 if (error)
353 return (error);
354 }
355 if (ap->a_fflag & FWRITE) {
356 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
357 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_td);
358 if (error)
359 return (error);
360 }
361 return (0);
362}
363
364/* ARGSUSED */
365static int
366fifo_kqfilter(ap)
367 struct vop_kqfilter_args /* {
368 struct vnode *a_vp;
369 struct knote *a_kn;
370 } */ *ap;
371{
372 struct fifoinfo *fi = ap->a_vp->v_fifoinfo;
373 struct socket *so;
374 struct sockbuf *sb;
375
376 switch (ap->a_kn->kn_filter) {
377 case EVFILT_READ:
378 ap->a_kn->kn_fop = &fiforead_filtops;
379 so = fi->fi_readsock;
380 sb = &so->so_rcv;
381 break;
382 case EVFILT_WRITE:
383 ap->a_kn->kn_fop = &fifowrite_filtops;
384 so = fi->fi_writesock;
385 sb = &so->so_snd;
386 break;
387 default:
388 return (1);
389 }
390
391 ap->a_kn->kn_hook = (caddr_t)so;
392
393 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
394 sb->sb_flags |= SB_KNOTE;
395
396 return (0);
397}
398
399static void
400filt_fifordetach(struct knote *kn)
401{
402 struct socket *so = (struct socket *)kn->kn_hook;
403
404 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
405 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
406 so->so_rcv.sb_flags &= ~SB_KNOTE;
407}
408
409static int
410filt_fiforead(struct knote *kn, long hint)
411{
412 struct socket *so = (struct socket *)kn->kn_hook;
413
414 kn->kn_data = so->so_rcv.sb_cc;
415 if (so->so_state & SS_CANTRCVMORE) {
416 kn->kn_flags |= EV_EOF;
417 return (1);
418 }
419 kn->kn_flags &= ~EV_EOF;
420 return (kn->kn_data > 0);
421}
422
423static void
424filt_fifowdetach(struct knote *kn)
425{
426 struct socket *so = (struct socket *)kn->kn_hook;
427
428 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
429 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
430 so->so_snd.sb_flags &= ~SB_KNOTE;
431}
432
433static int
434filt_fifowrite(struct knote *kn, long hint)
435{
436 struct socket *so = (struct socket *)kn->kn_hook;
437
438 kn->kn_data = sbspace(&so->so_snd);
439 if (so->so_state & SS_CANTSENDMORE) {
440 kn->kn_flags |= EV_EOF;
441 return (1);
442 }
443 kn->kn_flags &= ~EV_EOF;
444 return (kn->kn_data >= so->so_snd.sb_lowat);
445}
446
447/* ARGSUSED */
448static int
449fifo_poll(ap)
450 struct vop_poll_args /* {
451 struct vnode *a_vp;
452 int a_events;
453 struct ucred *a_cred;
454 struct thread *a_td;
455 } */ *ap;
456{
457 struct file filetmp;
458 int revents = 0;
459
460 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
461 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
462 if (filetmp.f_data)
463 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
464 ap->a_td);
465 }
466 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
467 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
468 if (filetmp.f_data)
469 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
470 ap->a_td);
471 }
472 return (revents);
473}
474
475/*
476 * Device close routine
477 */
478/* ARGSUSED */
479static int
480fifo_close(ap)
481 struct vop_close_args /* {
482 struct vnode *a_vp;
483 int a_fflag;
484 struct ucred *a_cred;
485 struct thread *a_td;
486 } */ *ap;
487{
488 register struct vnode *vp = ap->a_vp;
489 register struct fifoinfo *fip = vp->v_fifoinfo;
490 int error1, error2;
491
492 if (ap->a_fflag & FREAD) {
493 fip->fi_readers--;
494 if (fip->fi_readers == 0)
495 socantsendmore(fip->fi_writesock);
496 }
497 if (ap->a_fflag & FWRITE) {
498 fip->fi_writers--;
499 if (fip->fi_writers == 0)
500 socantrcvmore(fip->fi_readsock);
501 }
502 if (vp->v_usecount > 1)
503 return (0);
504 error1 = soclose(fip->fi_readsock);
505 error2 = soclose(fip->fi_writesock);
506 FREE(fip, M_VNODE);
507 vp->v_fifoinfo = NULL;
508 if (error1)
509 return (error1);
510 return (error2);
511}
512
513
514/*
515 * Print out internal contents of a fifo vnode.
516 */
517int
518fifo_printinfo(vp)
519 struct vnode *vp;
520{
521 register struct fifoinfo *fip = vp->v_fifoinfo;
522
523 printf(", fifo with %ld readers and %ld writers",
524 fip->fi_readers, fip->fi_writers);
525 return (0);
526}
527
528/*
529 * Print out the contents of a fifo vnode.
530 */
531static int
532fifo_print(ap)
533 struct vop_print_args /* {
534 struct vnode *a_vp;
535 } */ *ap;
536{
537
538 printf("tag VT_NON");
539 fifo_printinfo(ap->a_vp);
540 printf("\n");
541 return (0);
542}
543
544/*
545 * Return POSIX pathconf information applicable to fifo's.
546 */
547int
548fifo_pathconf(ap)
549 struct vop_pathconf_args /* {
550 struct vnode *a_vp;
551 int a_name;
552 int *a_retval;
553 } */ *ap;
554{
555
556 switch (ap->a_name) {
557 case _PC_LINK_MAX:
558 *ap->a_retval = LINK_MAX;
559 return (0);
560 case _PC_PIPE_BUF:
561 *ap->a_retval = PIPE_BUF;
562 return (0);
563 case _PC_CHOWN_RESTRICTED:
564 *ap->a_retval = 1;
565 return (0);
566 default:
567 return (EINVAL);
568 }
569 /* NOTREACHED */
570}
571
572/*
573 * Fifo advisory byte-level locks.
574 */
575/* ARGSUSED */
576static int
577fifo_advlock(ap)
578 struct vop_advlock_args /* {
579 struct vnode *a_vp;
580 caddr_t a_id;
581 int a_op;
582 struct flock *a_fl;
583 int a_flags;
584 } */ *ap;
585{
586
587 return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
588}
589
590/*
591 * Fifo bad operation
592 */
593static int
594fifo_badop()
595{
596
597 panic("fifo_badop called");
598 /* NOTREACHED */
599}
187 if (error) {
188 (void)soclose(rso);
189 free(fip, M_VNODE);
190 vp->v_fifoinfo = NULL;
191 return (error);
192 }
193 fip->fi_writesock = wso;
194 error = unp_connect2(wso, rso);
195 if (error) {
196 (void)soclose(wso);
197 (void)soclose(rso);
198 free(fip, M_VNODE);
199 vp->v_fifoinfo = NULL;
200 return (error);
201 }
202 fip->fi_readers = fip->fi_writers = 0;
203 wso->so_snd.sb_lowat = PIPE_BUF;
204 }
205 if (ap->a_mode & FREAD) {
206 fip->fi_readers++;
207 if (fip->fi_readers == 1) {
208 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
209 if (fip->fi_writers > 0) {
210 wakeup((caddr_t)&fip->fi_writers);
211 sowwakeup(fip->fi_writesock);
212 }
213 }
214 }
215 if (ap->a_mode & FWRITE) {
216 fip->fi_writers++;
217 if (fip->fi_writers == 1) {
218 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
219 if (fip->fi_readers > 0) {
220 wakeup((caddr_t)&fip->fi_readers);
221 sorwakeup(fip->fi_writesock);
222 }
223 }
224 }
225 if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
226 while (fip->fi_writers == 0) {
227 VOP_UNLOCK(vp, 0, td);
228 error = tsleep((caddr_t)&fip->fi_readers,
229 PCATCH | PSOCK, "fifoor", 0);
230 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
231 if (error)
232 goto bad;
233 }
234 }
235 if (ap->a_mode & FWRITE) {
236 if (ap->a_mode & O_NONBLOCK) {
237 if (fip->fi_readers == 0) {
238 error = ENXIO;
239 goto bad;
240 }
241 } else {
242 while (fip->fi_readers == 0) {
243 VOP_UNLOCK(vp, 0, td);
244 error = tsleep((caddr_t)&fip->fi_writers,
245 PCATCH | PSOCK, "fifoow", 0);
246 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
247 if (error)
248 goto bad;
249 }
250 }
251 }
252 return (0);
253bad:
254 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, td);
255 return (error);
256}
257
258/*
259 * Vnode op for read
260 */
261/* ARGSUSED */
262static int
263fifo_read(ap)
264 struct vop_read_args /* {
265 struct vnode *a_vp;
266 struct uio *a_uio;
267 int a_ioflag;
268 struct ucred *a_cred;
269 } */ *ap;
270{
271 struct uio *uio = ap->a_uio;
272 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
273 struct thread *td = uio->uio_td;
274 int error, startresid;
275
276#ifdef DIAGNOSTIC
277 if (uio->uio_rw != UIO_READ)
278 panic("fifo_read mode");
279#endif
280 if (uio->uio_resid == 0)
281 return (0);
282 if (ap->a_ioflag & IO_NDELAY)
283 rso->so_state |= SS_NBIO;
284 startresid = uio->uio_resid;
285 VOP_UNLOCK(ap->a_vp, 0, td);
286 error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
287 (struct mbuf **)0, (int *)0);
288 /*
289 * Clear EOF indication after first such return.
290 */
291 if (uio->uio_resid == startresid)
292 rso->so_state &= ~SS_CANTRCVMORE;
293 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
294 if (ap->a_ioflag & IO_NDELAY)
295 rso->so_state &= ~SS_NBIO;
296 return (error);
297}
298
299/*
300 * Vnode op for write
301 */
302/* ARGSUSED */
303static int
304fifo_write(ap)
305 struct vop_write_args /* {
306 struct vnode *a_vp;
307 struct uio *a_uio;
308 int a_ioflag;
309 struct ucred *a_cred;
310 } */ *ap;
311{
312 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
313 struct thread *td = ap->a_uio->uio_td;
314 int error;
315
316#ifdef DIAGNOSTIC
317 if (ap->a_uio->uio_rw != UIO_WRITE)
318 panic("fifo_write mode");
319#endif
320 if (ap->a_ioflag & IO_NDELAY)
321 wso->so_state |= SS_NBIO;
322 VOP_UNLOCK(ap->a_vp, 0, td);
323 error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
324 (struct mbuf *)0, 0, td);
325 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
326 if (ap->a_ioflag & IO_NDELAY)
327 wso->so_state &= ~SS_NBIO;
328 return (error);
329}
330
331/*
332 * Device ioctl operation.
333 */
334/* ARGSUSED */
335static int
336fifo_ioctl(ap)
337 struct vop_ioctl_args /* {
338 struct vnode *a_vp;
339 int a_command;
340 caddr_t a_data;
341 int a_fflag;
342 struct ucred *a_cred;
343 struct thread *a_td;
344 } */ *ap;
345{
346 struct file filetmp;
347 int error;
348
349 if (ap->a_command == FIONBIO)
350 return (0);
351 if (ap->a_fflag & FREAD) {
352 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
353 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_td);
354 if (error)
355 return (error);
356 }
357 if (ap->a_fflag & FWRITE) {
358 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
359 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_td);
360 if (error)
361 return (error);
362 }
363 return (0);
364}
365
366/* ARGSUSED */
367static int
368fifo_kqfilter(ap)
369 struct vop_kqfilter_args /* {
370 struct vnode *a_vp;
371 struct knote *a_kn;
372 } */ *ap;
373{
374 struct fifoinfo *fi = ap->a_vp->v_fifoinfo;
375 struct socket *so;
376 struct sockbuf *sb;
377
378 switch (ap->a_kn->kn_filter) {
379 case EVFILT_READ:
380 ap->a_kn->kn_fop = &fiforead_filtops;
381 so = fi->fi_readsock;
382 sb = &so->so_rcv;
383 break;
384 case EVFILT_WRITE:
385 ap->a_kn->kn_fop = &fifowrite_filtops;
386 so = fi->fi_writesock;
387 sb = &so->so_snd;
388 break;
389 default:
390 return (1);
391 }
392
393 ap->a_kn->kn_hook = (caddr_t)so;
394
395 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
396 sb->sb_flags |= SB_KNOTE;
397
398 return (0);
399}
400
401static void
402filt_fifordetach(struct knote *kn)
403{
404 struct socket *so = (struct socket *)kn->kn_hook;
405
406 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
407 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
408 so->so_rcv.sb_flags &= ~SB_KNOTE;
409}
410
411static int
412filt_fiforead(struct knote *kn, long hint)
413{
414 struct socket *so = (struct socket *)kn->kn_hook;
415
416 kn->kn_data = so->so_rcv.sb_cc;
417 if (so->so_state & SS_CANTRCVMORE) {
418 kn->kn_flags |= EV_EOF;
419 return (1);
420 }
421 kn->kn_flags &= ~EV_EOF;
422 return (kn->kn_data > 0);
423}
424
425static void
426filt_fifowdetach(struct knote *kn)
427{
428 struct socket *so = (struct socket *)kn->kn_hook;
429
430 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
431 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
432 so->so_snd.sb_flags &= ~SB_KNOTE;
433}
434
435static int
436filt_fifowrite(struct knote *kn, long hint)
437{
438 struct socket *so = (struct socket *)kn->kn_hook;
439
440 kn->kn_data = sbspace(&so->so_snd);
441 if (so->so_state & SS_CANTSENDMORE) {
442 kn->kn_flags |= EV_EOF;
443 return (1);
444 }
445 kn->kn_flags &= ~EV_EOF;
446 return (kn->kn_data >= so->so_snd.sb_lowat);
447}
448
449/* ARGSUSED */
450static int
451fifo_poll(ap)
452 struct vop_poll_args /* {
453 struct vnode *a_vp;
454 int a_events;
455 struct ucred *a_cred;
456 struct thread *a_td;
457 } */ *ap;
458{
459 struct file filetmp;
460 int revents = 0;
461
462 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
463 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
464 if (filetmp.f_data)
465 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
466 ap->a_td);
467 }
468 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
469 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
470 if (filetmp.f_data)
471 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
472 ap->a_td);
473 }
474 return (revents);
475}
476
477/*
478 * Device close routine
479 */
480/* ARGSUSED */
481static int
482fifo_close(ap)
483 struct vop_close_args /* {
484 struct vnode *a_vp;
485 int a_fflag;
486 struct ucred *a_cred;
487 struct thread *a_td;
488 } */ *ap;
489{
490 register struct vnode *vp = ap->a_vp;
491 register struct fifoinfo *fip = vp->v_fifoinfo;
492 int error1, error2;
493
494 if (ap->a_fflag & FREAD) {
495 fip->fi_readers--;
496 if (fip->fi_readers == 0)
497 socantsendmore(fip->fi_writesock);
498 }
499 if (ap->a_fflag & FWRITE) {
500 fip->fi_writers--;
501 if (fip->fi_writers == 0)
502 socantrcvmore(fip->fi_readsock);
503 }
504 if (vp->v_usecount > 1)
505 return (0);
506 error1 = soclose(fip->fi_readsock);
507 error2 = soclose(fip->fi_writesock);
508 FREE(fip, M_VNODE);
509 vp->v_fifoinfo = NULL;
510 if (error1)
511 return (error1);
512 return (error2);
513}
514
515
516/*
517 * Print out internal contents of a fifo vnode.
518 */
519int
520fifo_printinfo(vp)
521 struct vnode *vp;
522{
523 register struct fifoinfo *fip = vp->v_fifoinfo;
524
525 printf(", fifo with %ld readers and %ld writers",
526 fip->fi_readers, fip->fi_writers);
527 return (0);
528}
529
530/*
531 * Print out the contents of a fifo vnode.
532 */
533static int
534fifo_print(ap)
535 struct vop_print_args /* {
536 struct vnode *a_vp;
537 } */ *ap;
538{
539
540 printf("tag VT_NON");
541 fifo_printinfo(ap->a_vp);
542 printf("\n");
543 return (0);
544}
545
546/*
547 * Return POSIX pathconf information applicable to fifo's.
548 */
549int
550fifo_pathconf(ap)
551 struct vop_pathconf_args /* {
552 struct vnode *a_vp;
553 int a_name;
554 int *a_retval;
555 } */ *ap;
556{
557
558 switch (ap->a_name) {
559 case _PC_LINK_MAX:
560 *ap->a_retval = LINK_MAX;
561 return (0);
562 case _PC_PIPE_BUF:
563 *ap->a_retval = PIPE_BUF;
564 return (0);
565 case _PC_CHOWN_RESTRICTED:
566 *ap->a_retval = 1;
567 return (0);
568 default:
569 return (EINVAL);
570 }
571 /* NOTREACHED */
572}
573
574/*
575 * Fifo advisory byte-level locks.
576 */
577/* ARGSUSED */
578static int
579fifo_advlock(ap)
580 struct vop_advlock_args /* {
581 struct vnode *a_vp;
582 caddr_t a_id;
583 int a_op;
584 struct flock *a_fl;
585 int a_flags;
586 } */ *ap;
587{
588
589 return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
590}
591
592/*
593 * Fifo bad operation
594 */
595static int
596fifo_badop()
597{
598
599 panic("fifo_badop called");
600 /* NOTREACHED */
601}