Commit | Line | Data |
---|---|---|
984263bc MD |
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. | |
dc71b7ab | 13 | * 3. Neither the name of the University nor the names of its contributors |
984263bc MD |
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. | |
984263bc | 28 | */ |
aac0aabd | 29 | /* |
f9ad1101 | 30 | * Filesystem FIFO type ops. All entry points are MPSAFE. |
aac0aabd | 31 | */ |
984263bc MD |
32 | #include <sys/param.h> |
33 | #include <sys/systm.h> | |
34 | #include <sys/unistd.h> | |
35 | #include <sys/kernel.h> | |
36 | #include <sys/lock.h> | |
37 | #include <sys/malloc.h> | |
38 | #include <sys/vnode.h> | |
39 | #include <sys/socket.h> | |
40 | #include <sys/socketvar.h> | |
41 | #include <sys/filio.h> | |
42 | #include <sys/fcntl.h> | |
43 | #include <sys/file.h> | |
44 | #include <sys/event.h> | |
984263bc | 45 | #include <sys/un.h> |
87de5057 | 46 | |
6cef7136 | 47 | #include <sys/socketvar2.h> |
87de5057 | 48 | |
1f2de5d4 | 49 | #include "fifo.h" |
984263bc MD |
50 | |
51 | /* | |
52 | * This structure is associated with the FIFO vnode and stores | |
53 | * the state associated with the FIFO. | |
54 | */ | |
55 | struct fifoinfo { | |
56 | struct socket *fi_readsock; | |
57 | struct socket *fi_writesock; | |
58 | long fi_readers; | |
59 | long fi_writers; | |
60 | }; | |
61 | ||
f9ad1101 MD |
62 | #define FIFO_LOCK_POOL 128 |
63 | #define FIFO_LOCK_MASK (FIFO_LOCK_POOL - 1) | |
64 | ||
a6ee311a RG |
65 | static int fifo_badop (void); |
66 | static int fifo_print (struct vop_print_args *); | |
e62afb5f | 67 | static int fifo_lookup (struct vop_old_lookup_args *); |
a6ee311a RG |
68 | static int fifo_open (struct vop_open_args *); |
69 | static int fifo_close (struct vop_close_args *); | |
70 | static int fifo_read (struct vop_read_args *); | |
71 | static int fifo_write (struct vop_write_args *); | |
72 | static int fifo_ioctl (struct vop_ioctl_args *); | |
a6ee311a RG |
73 | static int fifo_kqfilter (struct vop_kqfilter_args *); |
74 | static int fifo_inactive (struct vop_inactive_args *); | |
75 | static int fifo_bmap (struct vop_bmap_args *); | |
76 | static int fifo_pathconf (struct vop_pathconf_args *); | |
77 | static int fifo_advlock (struct vop_advlock_args *); | |
984263bc MD |
78 | |
79 | static void filt_fifordetach(struct knote *kn); | |
80 | static int filt_fiforead(struct knote *kn, long hint); | |
81 | static void filt_fifowdetach(struct knote *kn); | |
82 | static int filt_fifowrite(struct knote *kn, long hint); | |
83 | ||
84 | static struct filterops fiforead_filtops = | |
4c91dbc9 | 85 | { FILTEROP_ISFD, NULL, filt_fifordetach, filt_fiforead }; |
984263bc | 86 | static struct filterops fifowrite_filtops = |
4c91dbc9 | 87 | { FILTEROP_ISFD, NULL, filt_fifowdetach, filt_fifowrite }; |
f9ad1101 | 88 | |
66a1ddf5 MD |
89 | struct vop_ops fifo_vnode_vops = { |
90 | .vop_default = vop_defaultop, | |
91 | .vop_access = (void *)vop_ebadf, | |
92 | .vop_advlock = fifo_advlock, | |
93 | .vop_bmap = fifo_bmap, | |
94 | .vop_close = fifo_close, | |
95 | .vop_old_create = (void *)fifo_badop, | |
96 | .vop_getattr = (void *)vop_ebadf, | |
97 | .vop_inactive = fifo_inactive, | |
98 | .vop_ioctl = fifo_ioctl, | |
99 | .vop_kqfilter = fifo_kqfilter, | |
100 | .vop_old_link = (void *)fifo_badop, | |
101 | .vop_old_lookup = fifo_lookup, | |
102 | .vop_old_mkdir = (void *)fifo_badop, | |
103 | .vop_old_mknod = (void *)fifo_badop, | |
104 | .vop_open = fifo_open, | |
105 | .vop_pathconf = fifo_pathconf, | |
66a1ddf5 MD |
106 | .vop_print = fifo_print, |
107 | .vop_read = fifo_read, | |
108 | .vop_readdir = (void *)fifo_badop, | |
109 | .vop_readlink = (void *)fifo_badop, | |
110 | .vop_reallocblks = (void *)fifo_badop, | |
111 | .vop_reclaim = (void *)vop_null, | |
112 | .vop_old_remove = (void *)fifo_badop, | |
113 | .vop_old_rename = (void *)fifo_badop, | |
114 | .vop_old_rmdir = (void *)fifo_badop, | |
115 | .vop_setattr = (void *)vop_ebadf, | |
116 | .vop_old_symlink = (void *)fifo_badop, | |
117 | .vop_write = fifo_write | |
984263bc | 118 | }; |
984263bc | 119 | |
66a1ddf5 | 120 | VNODEOP_SET(fifo_vnode_vops); |
984263bc | 121 | |
5fd012e0 MD |
122 | static MALLOC_DEFINE(M_FIFOINFO, "Fifo info", "Fifo info entries"); |
123 | ||
f9ad1101 MD |
124 | /* |
125 | * The vnode might be using a shared lock, we need an exclusive lock | |
126 | * for open/close sequencing. Create a little pool of locks. | |
127 | */ | |
128 | static struct lock fifo_locks[FIFO_LOCK_POOL]; | |
129 | ||
130 | static __inline | |
131 | void | |
132 | fifo_lock(struct vnode *vp) | |
133 | { | |
134 | int hv; | |
135 | ||
136 | hv = ((intptr_t)vp / sizeof(*vp)) & FIFO_LOCK_MASK; | |
137 | lockmgr(&fifo_locks[hv], LK_EXCLUSIVE); | |
138 | } | |
139 | ||
140 | static __inline | |
141 | void | |
142 | fifo_unlock(struct vnode *vp) | |
143 | { | |
144 | int hv; | |
145 | ||
146 | hv = ((intptr_t)vp / sizeof(*vp)) & FIFO_LOCK_MASK; | |
147 | lockmgr(&fifo_locks[hv], LK_RELEASE); | |
148 | } | |
149 | ||
150 | static void | |
151 | fifo_init(void) | |
152 | { | |
153 | int i; | |
154 | ||
155 | for (i = 0; i < FIFO_LOCK_POOL; ++i) | |
156 | lockinit(&fifo_locks[i], "fifolk", 0, 0); | |
157 | } | |
158 | SYSINIT(fifoinit, SI_SUB_PSEUDO, SI_ORDER_ANY, fifo_init, NULL); | |
159 | ||
b5f12e21 | 160 | /* |
31bd717a | 161 | * fifo_vnoperate() |
b5f12e21 | 162 | */ |
984263bc | 163 | int |
b5f12e21 | 164 | fifo_vnoperate(struct vop_generic_args *ap) |
984263bc | 165 | { |
66a1ddf5 | 166 | return (VOCALL(&fifo_vnode_vops, ap)); |
984263bc MD |
167 | } |
168 | ||
169 | /* | |
170 | * Trivial lookup routine that always fails. | |
b5f12e21 CP |
171 | * |
172 | * fifo_lookup(struct vnode *a_dvp, struct vnode **a_vpp, | |
173 | * struct componentname *a_cnp) | |
984263bc MD |
174 | */ |
175 | /* ARGSUSED */ | |
176 | static int | |
e62afb5f | 177 | fifo_lookup(struct vop_old_lookup_args *ap) |
984263bc | 178 | { |
984263bc MD |
179 | *ap->a_vpp = NULL; |
180 | return (ENOTDIR); | |
181 | } | |
182 | ||
f9ad1101 MD |
183 | /* |
184 | * Create/destroy the socket pairs for the fifo | |
185 | */ | |
186 | static | |
187 | struct fifoinfo * | |
188 | fifo_fip_create(int *errorp) | |
189 | { | |
190 | struct thread *td = curthread; | |
191 | struct fifoinfo *fip; | |
192 | struct socket *rso, *wso; | |
193 | ||
194 | fip = kmalloc(sizeof(*fip), M_FIFOINFO, M_WAITOK); | |
195 | *errorp = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, td); | |
196 | if (*errorp) { | |
197 | kfree(fip, M_FIFOINFO); | |
198 | return NULL; | |
199 | } | |
200 | rso->so_options &= ~SO_LINGER; | |
201 | fip->fi_readsock = rso; | |
202 | *errorp = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, td); | |
203 | if (*errorp) { | |
204 | soclose(rso, FNONBLOCK); | |
205 | kfree(fip, M_FIFOINFO); | |
206 | return NULL; | |
207 | } | |
208 | wso->so_options &= ~SO_LINGER; | |
209 | fip->fi_writesock = wso; | |
22db3608 | 210 | *errorp = unp_connect2(wso, rso, td->td_ucred); |
f9ad1101 MD |
211 | if (*errorp) { |
212 | soclose(wso, FNONBLOCK); | |
213 | soclose(rso, FNONBLOCK); | |
214 | kfree(fip, M_FIFOINFO); | |
215 | return NULL; | |
216 | } | |
217 | fip->fi_readers = fip->fi_writers = 0; | |
218 | wso->so_snd.ssb_lowat = PIPE_BUF; | |
219 | sosetstate(rso, SS_CANTRCVMORE); | |
220 | ||
221 | return fip; | |
222 | } | |
223 | ||
224 | static int | |
225 | fifo_fip_destroy(struct fifoinfo *fip) | |
226 | { | |
227 | int error1, error; | |
228 | ||
229 | error1 = soclose(fip->fi_readsock, FNONBLOCK); | |
230 | error = soclose(fip->fi_writesock, FNONBLOCK); | |
231 | kfree(fip, M_FIFOINFO); | |
232 | if (error1) | |
233 | error = error1; | |
234 | return error; | |
235 | } | |
236 | ||
984263bc MD |
237 | /* |
238 | * Open called to set up a new instance of a fifo or | |
239 | * to find an active instance of a fifo. | |
b5f12e21 CP |
240 | * |
241 | * fifo_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, | |
b478fdce | 242 | * struct file *a_fp) |
984263bc MD |
243 | */ |
244 | /* ARGSUSED */ | |
245 | static int | |
b5f12e21 | 246 | fifo_open(struct vop_open_args *ap) |
984263bc MD |
247 | { |
248 | struct vnode *vp = ap->a_vp; | |
249 | struct fifoinfo *fip; | |
984263bc MD |
250 | int error; |
251 | ||
f9ad1101 MD |
252 | error = 0; |
253 | ||
254 | /* | |
255 | * Create the fip if necessary | |
256 | */ | |
257 | fifo_lock(vp); | |
984263bc | 258 | if ((fip = vp->v_fifoinfo) == NULL) { |
f9ad1101 MD |
259 | fip = fifo_fip_create(&error); |
260 | if (fip == NULL) { | |
261 | fifo_unlock(vp); | |
262 | return error; | |
984263bc | 263 | } |
f9ad1101 | 264 | vp->v_fifoinfo = fip; |
984263bc | 265 | } |
f9ad1101 MD |
266 | |
267 | /* | |
268 | * Adjust fi_readers and fi_writers interlocked and issue wakeups | |
269 | * as appropriate. | |
270 | */ | |
984263bc MD |
271 | if (ap->a_mode & FREAD) { |
272 | fip->fi_readers++; | |
273 | if (fip->fi_readers == 1) { | |
0f2e13ef | 274 | soisreconnected(fip->fi_writesock); |
984263bc MD |
275 | if (fip->fi_writers > 0) { |
276 | wakeup((caddr_t)&fip->fi_writers); | |
277 | sowwakeup(fip->fi_writesock); | |
278 | } | |
279 | } | |
280 | } | |
281 | if (ap->a_mode & FWRITE) { | |
282 | fip->fi_writers++; | |
283 | if (fip->fi_writers == 1) { | |
0f2e13ef | 284 | soisreconnected(fip->fi_readsock); |
984263bc MD |
285 | if (fip->fi_readers > 0) { |
286 | wakeup((caddr_t)&fip->fi_readers); | |
287 | sorwakeup(fip->fi_writesock); | |
288 | } | |
289 | } | |
290 | } | |
f9ad1101 MD |
291 | |
292 | /* | |
293 | * Handle blocking as appropriate | |
294 | */ | |
984263bc MD |
295 | if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { |
296 | if (fip->fi_writers == 0) { | |
f9ad1101 | 297 | fifo_unlock(vp); |
a11aaa81 | 298 | vn_unlock(vp); |
984263bc | 299 | error = tsleep((caddr_t)&fip->fi_readers, |
f9ad1101 | 300 | PCATCH, "fifoor", 0); |
ca466bae | 301 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
f9ad1101 | 302 | fifo_lock(vp); |
984263bc MD |
303 | if (error) |
304 | goto bad; | |
305 | /* | |
306 | * We must have got woken up because we had a writer. | |
307 | * That (and not still having one) is the condition | |
308 | * that we must wait for. | |
309 | */ | |
310 | } | |
311 | } | |
312 | if (ap->a_mode & FWRITE) { | |
313 | if (ap->a_mode & O_NONBLOCK) { | |
314 | if (fip->fi_readers == 0) { | |
315 | error = ENXIO; | |
316 | goto bad; | |
317 | } | |
318 | } else { | |
319 | if (fip->fi_readers == 0) { | |
f9ad1101 | 320 | fifo_unlock(vp); |
a11aaa81 | 321 | vn_unlock(vp); |
984263bc | 322 | error = tsleep((caddr_t)&fip->fi_writers, |
f9ad1101 | 323 | PCATCH, "fifoow", 0); |
ca466bae | 324 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
f9ad1101 | 325 | fifo_lock(vp); |
984263bc MD |
326 | if (error) |
327 | goto bad; | |
328 | /* | |
329 | * We must have got woken up because we had | |
330 | * a reader. That (and not still having one) | |
331 | * is the condition that we must wait for. | |
332 | */ | |
333 | } | |
334 | } | |
335 | } | |
2247fe02 | 336 | vsetflags(vp, VNOTSEEKABLE); |
aac0aabd | 337 | error = vop_stdopen(ap); |
f9ad1101 MD |
338 | fifo_unlock(vp); |
339 | ||
aac0aabd | 340 | return (error); |
f9ad1101 | 341 | |
984263bc | 342 | bad: |
f9ad1101 MD |
343 | if (ap->a_mode & FREAD) { |
344 | fip->fi_readers--; | |
345 | if (fip->fi_readers == 0) | |
346 | soisdisconnected(fip->fi_writesock); | |
347 | } | |
348 | if (ap->a_mode & FWRITE) { | |
349 | fip->fi_writers--; | |
350 | if (fip->fi_writers == 0) | |
351 | soisdisconnected(fip->fi_readsock); | |
352 | } | |
353 | if (fip->fi_readers == 0 && fip->fi_writers == 0) { | |
354 | vp->v_fifoinfo = NULL; | |
355 | (void)fifo_fip_destroy(fip); | |
356 | } | |
357 | fifo_unlock(vp); | |
358 | ||
984263bc MD |
359 | return (error); |
360 | } | |
361 | ||
362 | /* | |
363 | * Vnode op for read | |
b5f12e21 CP |
364 | * |
365 | * fifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag, | |
366 | * struct ucred *a_cred) | |
984263bc MD |
367 | */ |
368 | /* ARGSUSED */ | |
369 | static int | |
b5f12e21 | 370 | fifo_read(struct vop_read_args *ap) |
984263bc MD |
371 | { |
372 | struct uio *uio = ap->a_uio; | |
3b998fa9 MD |
373 | struct vnode *vp = ap->a_vp; |
374 | struct socket *rso = vp->v_fifoinfo->fi_readsock; | |
a51fb308 | 375 | int error; |
9ba76b73 | 376 | int flags; |
984263bc MD |
377 | |
378 | #ifdef DIAGNOSTIC | |
379 | if (uio->uio_rw != UIO_READ) | |
380 | panic("fifo_read mode"); | |
381 | #endif | |
382 | if (uio->uio_resid == 0) | |
383 | return (0); | |
384 | if (ap->a_ioflag & IO_NDELAY) | |
9ba76b73 MD |
385 | flags = MSG_FNONBLOCKING; |
386 | else | |
387 | flags = 0; | |
3b998fa9 MD |
388 | vn_unlock(vp); |
389 | lwkt_gettoken(&vp->v_token); | |
d8a9a23b | 390 | error = soreceive(rso, NULL, uio, NULL, NULL, &flags); |
3b998fa9 MD |
391 | lwkt_reltoken(&vp->v_token); |
392 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | |
984263bc MD |
393 | return (error); |
394 | } | |
395 | ||
396 | /* | |
397 | * Vnode op for write | |
b5f12e21 CP |
398 | * |
399 | * fifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag, | |
400 | * struct ucred *a_cred) | |
984263bc MD |
401 | */ |
402 | /* ARGSUSED */ | |
403 | static int | |
b5f12e21 | 404 | fifo_write(struct vop_write_args *ap) |
984263bc | 405 | { |
dadab5e9 | 406 | struct thread *td = ap->a_uio->uio_td; |
3b998fa9 MD |
407 | struct vnode *vp = ap->a_vp; |
408 | struct socket *wso = vp->v_fifoinfo->fi_writesock; | |
984263bc | 409 | int error; |
9ba76b73 | 410 | int flags; |
984263bc MD |
411 | |
412 | #ifdef DIAGNOSTIC | |
413 | if (ap->a_uio->uio_rw != UIO_WRITE) | |
414 | panic("fifo_write mode"); | |
415 | #endif | |
416 | if (ap->a_ioflag & IO_NDELAY) | |
9ba76b73 MD |
417 | flags = MSG_FNONBLOCKING; |
418 | else | |
419 | flags = 0; | |
3b998fa9 MD |
420 | vn_unlock(vp); |
421 | lwkt_gettoken(&vp->v_token); | |
60233e58 | 422 | error = sosend(wso, NULL, ap->a_uio, 0, NULL, flags, td); |
3b998fa9 MD |
423 | lwkt_reltoken(&vp->v_token); |
424 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | |
984263bc MD |
425 | return (error); |
426 | } | |
427 | ||
428 | /* | |
429 | * Device ioctl operation. | |
b5f12e21 CP |
430 | * |
431 | * fifo_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, int a_fflag, | |
87baaf0c | 432 | * struct ucred *a_cred, struct sysmsg *a_sysmsg) |
984263bc MD |
433 | */ |
434 | /* ARGSUSED */ | |
435 | static int | |
b5f12e21 | 436 | fifo_ioctl(struct vop_ioctl_args *ap) |
984263bc | 437 | { |
9443ca22 | 438 | struct file filetmp; /* Local */ |
3b998fa9 | 439 | struct vnode *vp = ap->a_vp; |
984263bc MD |
440 | int error; |
441 | ||
984263bc | 442 | if (ap->a_fflag & FREAD) { |
3b998fa9 MD |
443 | filetmp.f_data = vp->v_fifoinfo->fi_readsock; |
444 | lwkt_gettoken(&vp->v_token); | |
87baaf0c MD |
445 | error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, |
446 | ap->a_cred, ap->a_sysmsg); | |
3b998fa9 | 447 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
448 | if (error) |
449 | return (error); | |
450 | } | |
451 | if (ap->a_fflag & FWRITE) { | |
3b998fa9 MD |
452 | filetmp.f_data = vp->v_fifoinfo->fi_writesock; |
453 | lwkt_gettoken(&vp->v_token); | |
87baaf0c MD |
454 | error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, |
455 | ap->a_cred, ap->a_sysmsg); | |
3b998fa9 | 456 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
457 | if (error) |
458 | return (error); | |
459 | } | |
460 | return (0); | |
461 | } | |
462 | ||
b5f12e21 CP |
463 | /* |
464 | * fifo_kqfilter(struct vnode *a_vp, struct knote *a_kn) | |
465 | */ | |
984263bc MD |
466 | /* ARGSUSED */ |
467 | static int | |
b5f12e21 | 468 | fifo_kqfilter(struct vop_kqfilter_args *ap) |
984263bc | 469 | { |
aac0aabd MD |
470 | struct vnode *vp = ap->a_vp; |
471 | struct fifoinfo *fi = vp->v_fifoinfo; | |
984263bc | 472 | struct socket *so; |
6d49aa6f | 473 | struct signalsockbuf *ssb; |
984263bc | 474 | |
3b998fa9 | 475 | lwkt_gettoken(&vp->v_token); |
b58e725b | 476 | |
984263bc MD |
477 | switch (ap->a_kn->kn_filter) { |
478 | case EVFILT_READ: | |
479 | ap->a_kn->kn_fop = &fiforead_filtops; | |
480 | so = fi->fi_readsock; | |
6d49aa6f | 481 | ssb = &so->so_rcv; |
984263bc MD |
482 | break; |
483 | case EVFILT_WRITE: | |
484 | ap->a_kn->kn_fop = &fifowrite_filtops; | |
485 | so = fi->fi_writesock; | |
6d49aa6f | 486 | ssb = &so->so_snd; |
984263bc MD |
487 | break; |
488 | default: | |
3b998fa9 | 489 | lwkt_reltoken(&vp->v_token); |
b287d649 | 490 | return (EOPNOTSUPP); |
984263bc MD |
491 | } |
492 | ||
aac0aabd | 493 | ap->a_kn->kn_hook = (caddr_t)vp; |
6d49aa6f | 494 | ssb_insert_knote(ssb, ap->a_kn); |
984263bc | 495 | |
3b998fa9 | 496 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
497 | return (0); |
498 | } | |
499 | ||
500 | static void | |
501 | filt_fifordetach(struct knote *kn) | |
502 | { | |
aac0aabd MD |
503 | struct vnode *vp = (void *)kn->kn_hook; |
504 | struct socket *so = vp->v_fifoinfo->fi_readsock; | |
984263bc | 505 | |
3b998fa9 | 506 | lwkt_gettoken(&vp->v_token); |
6d49aa6f | 507 | ssb_remove_knote(&so->so_rcv, kn); |
3b998fa9 | 508 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
509 | } |
510 | ||
511 | static int | |
512 | filt_fiforead(struct knote *kn, long hint) | |
513 | { | |
aac0aabd | 514 | struct vnode *vp = (void *)kn->kn_hook; |
7a5447ef | 515 | struct socket *so = vp->v_fifoinfo->fi_readsock; |
984263bc | 516 | |
3b998fa9 | 517 | lwkt_gettoken(&vp->v_token); |
6d49aa6f | 518 | kn->kn_data = so->so_rcv.ssb_cc; |
010f86dc SZ |
519 | if ((kn->kn_sfflags & NOTE_OLDAPI) == 0 && |
520 | so->so_state & SS_ISDISCONNECTED) { | |
3bcb6e5e SZ |
521 | if (kn->kn_data == 0) |
522 | kn->kn_flags |= EV_NODATA; | |
added858 | 523 | kn->kn_flags |= EV_EOF | EV_HUP; |
3b998fa9 | 524 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
525 | return (1); |
526 | } | |
added858 | 527 | kn->kn_flags &= ~(EV_EOF | EV_HUP | EV_NODATA); |
3b998fa9 | 528 | lwkt_reltoken(&vp->v_token); |
6df899ee MD |
529 | if ((kn->kn_sfflags & NOTE_HUPONLY) == 0) |
530 | return (kn->kn_data > 0); | |
531 | return 0; | |
984263bc MD |
532 | } |
533 | ||
534 | static void | |
535 | filt_fifowdetach(struct knote *kn) | |
536 | { | |
aac0aabd MD |
537 | struct vnode *vp = (void *)kn->kn_hook; |
538 | struct socket *so = vp->v_fifoinfo->fi_writesock; | |
984263bc | 539 | |
3b998fa9 | 540 | lwkt_gettoken(&vp->v_token); |
6d49aa6f | 541 | ssb_remove_knote(&so->so_snd, kn); |
3b998fa9 | 542 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
543 | } |
544 | ||
545 | static int | |
546 | filt_fifowrite(struct knote *kn, long hint) | |
547 | { | |
aac0aabd MD |
548 | struct vnode *vp = (void *)kn->kn_hook; |
549 | struct socket *so = vp->v_fifoinfo->fi_writesock; | |
984263bc | 550 | |
3b998fa9 | 551 | lwkt_gettoken(&vp->v_token); |
6d49aa6f | 552 | kn->kn_data = ssb_space(&so->so_snd); |
0f2e13ef | 553 | if (so->so_state & SS_ISDISCONNECTED) { |
added858 | 554 | kn->kn_flags |= EV_EOF | EV_HUP | EV_NODATA; |
3b998fa9 | 555 | lwkt_reltoken(&vp->v_token); |
984263bc MD |
556 | return (1); |
557 | } | |
added858 | 558 | kn->kn_flags &= ~(EV_EOF | EV_HUP | EV_NODATA); |
3b998fa9 | 559 | lwkt_reltoken(&vp->v_token); |
6d49aa6f | 560 | return (kn->kn_data >= so->so_snd.ssb_lowat); |
984263bc MD |
561 | } |
562 | ||
b5f12e21 | 563 | /* |
b478fdce | 564 | * fifo_inactive(struct vnode *a_vp) |
b5f12e21 | 565 | */ |
984263bc | 566 | static int |
b5f12e21 | 567 | fifo_inactive(struct vop_inactive_args *ap) |
984263bc | 568 | { |
984263bc MD |
569 | return (0); |
570 | } | |
571 | ||
572 | /* | |
573 | * This is a noop, simply returning what one has been given. | |
b5f12e21 | 574 | * |
08daea96 | 575 | * fifo_bmap(struct vnode *a_vp, off_t a_loffset, |
54078292 | 576 | * off_t *a_doffsetp, int *a_runp, int *a_runb) |
984263bc MD |
577 | */ |
578 | static int | |
b5f12e21 | 579 | fifo_bmap(struct vop_bmap_args *ap) |
984263bc | 580 | { |
54078292 MD |
581 | if (ap->a_doffsetp != NULL) |
582 | *ap->a_doffsetp = ap->a_loffset; | |
984263bc MD |
583 | if (ap->a_runp != NULL) |
584 | *ap->a_runp = 0; | |
585 | if (ap->a_runb != NULL) | |
586 | *ap->a_runb = 0; | |
587 | return (0); | |
588 | } | |
589 | ||
590 | /* | |
591 | * Device close routine | |
b5f12e21 | 592 | * |
b478fdce | 593 | * fifo_close(struct vnode *a_vp, int a_fflag) |
984263bc MD |
594 | */ |
595 | /* ARGSUSED */ | |
596 | static int | |
b5f12e21 | 597 | fifo_close(struct vop_close_args *ap) |
984263bc | 598 | { |
0e99e805 | 599 | struct vnode *vp = ap->a_vp; |
aac0aabd | 600 | struct fifoinfo *fip; |
f9ad1101 | 601 | int error; |
984263bc | 602 | |
f9ad1101 | 603 | fifo_lock(vp); |
aac0aabd | 604 | fip = vp->v_fifoinfo; |
f9ad1101 MD |
605 | if (fip == NULL) { |
606 | vop_stdclose(ap); | |
607 | fifo_unlock(vp); | |
608 | return 0; | |
609 | } | |
984263bc MD |
610 | if (ap->a_fflag & FREAD) { |
611 | fip->fi_readers--; | |
612 | if (fip->fi_readers == 0) | |
0f2e13ef | 613 | soisdisconnected(fip->fi_writesock); |
984263bc MD |
614 | } |
615 | if (ap->a_fflag & FWRITE) { | |
616 | fip->fi_writers--; | |
617 | if (fip->fi_writers == 0) | |
0f2e13ef | 618 | soisdisconnected(fip->fi_readsock); |
984263bc | 619 | } |
f9ad1101 MD |
620 | if (fip->fi_readers == 0 && fip->fi_writers == 0) { |
621 | vp->v_fifoinfo = NULL; | |
622 | error = fifo_fip_destroy(fip); | |
aac0aabd | 623 | } else { |
f9ad1101 | 624 | error = 0; |
aac0aabd | 625 | } |
f9ad1101 MD |
626 | vop_stdclose(ap); |
627 | fifo_unlock(vp); | |
984263bc | 628 | |
f9ad1101 MD |
629 | return error; |
630 | } | |
984263bc MD |
631 | |
632 | /* | |
633 | * Print out internal contents of a fifo vnode. | |
634 | */ | |
635 | int | |
b5f12e21 | 636 | fifo_printinfo(struct vnode *vp) |
984263bc | 637 | { |
0e99e805 | 638 | struct fifoinfo *fip = vp->v_fifoinfo; |
984263bc | 639 | |
086c1d7e | 640 | kprintf(", fifo with %ld readers and %ld writers", |
984263bc MD |
641 | fip->fi_readers, fip->fi_writers); |
642 | return (0); | |
643 | } | |
644 | ||
645 | /* | |
646 | * Print out the contents of a fifo vnode. | |
b5f12e21 CP |
647 | * |
648 | * fifo_print(struct vnode *a_vp) | |
984263bc MD |
649 | */ |
650 | static int | |
b5f12e21 | 651 | fifo_print(struct vop_print_args *ap) |
984263bc | 652 | { |
086c1d7e | 653 | kprintf("tag VT_NON"); |
984263bc | 654 | fifo_printinfo(ap->a_vp); |
086c1d7e | 655 | kprintf("\n"); |
984263bc MD |
656 | return (0); |
657 | } | |
658 | ||
659 | /* | |
660 | * Return POSIX pathconf information applicable to fifo's. | |
b5f12e21 CP |
661 | * |
662 | * fifo_pathconf(struct vnode *a_vp, int a_name, int *a_retval) | |
984263bc MD |
663 | */ |
664 | int | |
b5f12e21 | 665 | fifo_pathconf(struct vop_pathconf_args *ap) |
984263bc | 666 | { |
984263bc MD |
667 | switch (ap->a_name) { |
668 | case _PC_LINK_MAX: | |
669 | *ap->a_retval = LINK_MAX; | |
670 | return (0); | |
671 | case _PC_PIPE_BUF: | |
672 | *ap->a_retval = PIPE_BUF; | |
673 | return (0); | |
674 | case _PC_CHOWN_RESTRICTED: | |
675 | *ap->a_retval = 1; | |
676 | return (0); | |
677 | default: | |
678 | return (EINVAL); | |
679 | } | |
680 | /* NOTREACHED */ | |
681 | } | |
682 | ||
683 | /* | |
684 | * Fifo advisory byte-level locks. | |
b5f12e21 CP |
685 | * |
686 | * fifo_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl, | |
687 | * int a_flags) | |
984263bc MD |
688 | */ |
689 | /* ARGSUSED */ | |
690 | static int | |
b5f12e21 | 691 | fifo_advlock(struct vop_advlock_args *ap) |
984263bc | 692 | { |
71c18fe3 | 693 | return ((ap->a_flags & F_POSIX) ? EINVAL : EOPNOTSUPP); |
984263bc MD |
694 | } |
695 | ||
696 | /* | |
697 | * Fifo bad operation | |
698 | */ | |
699 | static int | |
b5f12e21 | 700 | fifo_badop(void) |
984263bc | 701 | { |
984263bc MD |
702 | panic("fifo_badop called"); |
703 | /* NOTREACHED */ | |
704 | } |