]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
de355530 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
de355530 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
de355530 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ | |
23 | /* | |
24 | * Copyright (c) 1990, 1993, 1995 | |
25 | * The Regents of the University of California. All rights reserved. | |
26 | * | |
27 | * Redistribution and use in source and binary forms, with or without | |
28 | * modification, are permitted provided that the following conditions | |
29 | * are met: | |
30 | * 1. Redistributions of source code must retain the above copyright | |
31 | * notice, this list of conditions and the following disclaimer. | |
32 | * 2. Redistributions in binary form must reproduce the above copyright | |
33 | * notice, this list of conditions and the following disclaimer in the | |
34 | * documentation and/or other materials provided with the distribution. | |
35 | * 3. All advertising materials mentioning features or use of this software | |
36 | * must display the following acknowledgement: | |
37 | * This product includes software developed by the University of | |
38 | * California, Berkeley and its contributors. | |
39 | * 4. Neither the name of the University nor the names of its contributors | |
40 | * may be used to endorse or promote products derived from this software | |
41 | * without specific prior written permission. | |
42 | * | |
43 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
53 | * SUCH DAMAGE. | |
54 | * | |
55 | * @(#)fifo_vnops.c 8.4 (Berkeley) 8/10/94 | |
56 | */ | |
57 | ||
58 | #include <sys/param.h> | |
59 | #include <sys/proc.h> | |
60 | #include <sys/time.h> | |
61 | #include <sys/namei.h> | |
62 | #include <sys/vnode.h> | |
63 | #include <sys/socket.h> | |
64 | #include <sys/socketvar.h> | |
65 | #include <sys/stat.h> | |
66 | #include <sys/systm.h> | |
67 | #include <sys/ioctl.h> | |
68 | #include <sys/file.h> | |
69 | #include <sys/errno.h> | |
70 | #include <sys/malloc.h> | |
71 | #include <miscfs/fifofs/fifo.h> | |
72 | #include <vfs/vfs_support.h> | |
73 | ||
74 | /* | |
75 | * This structure is associated with the FIFO vnode and stores | |
76 | * the state associated with the FIFO. | |
77 | */ | |
78 | struct fifoinfo { | |
79 | struct socket *fi_readsock; | |
80 | struct socket *fi_writesock; | |
81 | long fi_readers; | |
82 | long fi_writers; | |
83 | }; | |
84 | ||
85 | #define VOPFUNC int (*)(void *) | |
86 | ||
87 | int (**fifo_vnodeop_p)(void *); | |
88 | struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { | |
89 | { &vop_default_desc, (VOPFUNC)vn_default_error }, | |
90 | { &vop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */ | |
0b4e3aa0 A |
91 | { &vop_create_desc, (VOPFUNC)err_create }, /* create */ |
92 | { &vop_mknod_desc, (VOPFUNC)err_mknod }, /* mknod */ | |
1c79356b A |
93 | { &vop_open_desc, (VOPFUNC)fifo_open }, /* open */ |
94 | { &vop_close_desc, (VOPFUNC)fifo_close }, /* close */ | |
95 | { &vop_access_desc, (VOPFUNC)fifo_access }, /* access */ | |
96 | { &vop_getattr_desc, (VOPFUNC)fifo_getattr }, /* getattr */ | |
97 | { &vop_setattr_desc, (VOPFUNC)fifo_setattr }, /* setattr */ | |
98 | { &vop_read_desc, (VOPFUNC)fifo_read }, /* read */ | |
99 | { &vop_write_desc, (VOPFUNC)fifo_write }, /* write */ | |
100 | { &vop_lease_desc, (VOPFUNC)fifo_lease_check }, /* lease */ | |
101 | { &vop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */ | |
102 | { &vop_select_desc, (VOPFUNC)fifo_select }, /* select */ | |
103 | { &vop_revoke_desc, (VOPFUNC)fifo_revoke }, /* revoke */ | |
0b4e3aa0 | 104 | { &vop_mmap_desc, (VOPFUNC)err_mmap }, /* mmap */ |
1c79356b | 105 | { &vop_fsync_desc, (VOPFUNC)fifo_fsync }, /* fsync */ |
0b4e3aa0 A |
106 | { &vop_seek_desc, (VOPFUNC)err_seek }, /* seek */ |
107 | { &vop_remove_desc, (VOPFUNC)err_remove }, /* remove */ | |
108 | { &vop_link_desc, (VOPFUNC)err_link }, /* link */ | |
109 | { &vop_rename_desc, (VOPFUNC)err_rename }, /* rename */ | |
110 | { &vop_mkdir_desc, (VOPFUNC)err_mkdir }, /* mkdir */ | |
111 | { &vop_rmdir_desc, (VOPFUNC)err_rmdir }, /* rmdir */ | |
112 | { &vop_symlink_desc, (VOPFUNC)err_symlink }, /* symlink */ | |
113 | { &vop_readdir_desc, (VOPFUNC)err_readdir }, /* readdir */ | |
114 | { &vop_readlink_desc, (VOPFUNC)err_readlink }, /* readlink */ | |
115 | { &vop_abortop_desc, (VOPFUNC)err_abortop }, /* abortop */ | |
1c79356b A |
116 | { &vop_inactive_desc, (VOPFUNC)fifo_inactive }, /* inactive */ |
117 | { &vop_reclaim_desc, (VOPFUNC)fifo_reclaim }, /* reclaim */ | |
118 | { &vop_lock_desc, (VOPFUNC)fifo_lock }, /* lock */ | |
119 | { &vop_unlock_desc, (VOPFUNC)fifo_unlock }, /* unlock */ | |
120 | { &vop_bmap_desc, (VOPFUNC)fifo_bmap }, /* bmap */ | |
0b4e3aa0 | 121 | { &vop_strategy_desc, (VOPFUNC)err_strategy }, /* strategy */ |
1c79356b A |
122 | { &vop_print_desc, (VOPFUNC)fifo_print }, /* print */ |
123 | { &vop_islocked_desc, (VOPFUNC)fifo_islocked }, /* islocked */ | |
124 | { &vop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */ | |
125 | { &vop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */ | |
0b4e3aa0 A |
126 | { &vop_blkatoff_desc, (VOPFUNC)err_blkatoff }, /* blkatoff */ |
127 | { &vop_valloc_desc, (VOPFUNC)err_valloc }, /* valloc */ | |
128 | { &vop_vfree_desc, (VOPFUNC)err_vfree }, /* vfree */ | |
1c79356b A |
129 | { &vop_truncate_desc, (VOPFUNC)fifo_truncate }, /* truncate */ |
130 | { &vop_update_desc, (VOPFUNC)fifo_update }, /* update */ | |
131 | { &vop_bwrite_desc, (VOPFUNC)fifo_bwrite }, /* bwrite */ | |
132 | { &vop_pagein_desc, (VOPFUNC)err_pagein }, /* Pagein */ | |
133 | { &vop_pageout_desc, (VOPFUNC)err_pageout }, /* Pageout */ | |
134 | { &vop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copyfile */ | |
135 | { &vop_blktooff_desc, (VOPFUNC)err_blktooff }, /* blktooff */ | |
136 | { &vop_offtoblk_desc, (VOPFUNC)err_offtoblk }, /* offtoblk */ | |
137 | { &vop_cmap_desc, (VOPFUNC)err_cmap }, /* cmap */ | |
138 | { (struct vnodeop_desc*)NULL, (int(*)())NULL } | |
139 | }; | |
140 | struct vnodeopv_desc fifo_vnodeop_opv_desc = | |
141 | { &fifo_vnodeop_p, fifo_vnodeop_entries }; | |
142 | ||
143 | /* | |
144 | * Trivial lookup routine that always fails. | |
145 | */ | |
146 | /* ARGSUSED */ | |
147 | fifo_lookup(ap) | |
148 | struct vop_lookup_args /* { | |
149 | struct vnode * a_dvp; | |
150 | struct vnode ** a_vpp; | |
151 | struct componentname * a_cnp; | |
152 | } */ *ap; | |
153 | { | |
154 | ||
155 | *ap->a_vpp = NULL; | |
156 | return (ENOTDIR); | |
157 | } | |
158 | ||
159 | /* | |
160 | * Open called to set up a new instance of a fifo or | |
161 | * to find an active instance of a fifo. | |
162 | */ | |
163 | /* ARGSUSED */ | |
164 | fifo_open(ap) | |
165 | struct vop_open_args /* { | |
166 | struct vnode *a_vp; | |
167 | int a_mode; | |
168 | struct ucred *a_cred; | |
169 | struct proc *a_p; | |
170 | } */ *ap; | |
171 | { | |
172 | struct vnode *vp = ap->a_vp; | |
173 | struct fifoinfo *fip; | |
174 | struct proc *p = ap->a_p; | |
175 | struct socket *rso, *wso; | |
176 | int error; | |
177 | ||
178 | if ((fip = vp->v_fifoinfo) == NULL) { | |
179 | MALLOC_ZONE(fip, struct fifoinfo *, | |
180 | sizeof(*fip), M_VNODE, M_WAITOK); | |
181 | vp->v_fifoinfo = fip; | |
182 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
183 | if (error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) { | |
184 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
185 | _FREE_ZONE(fip, sizeof *fip, M_VNODE); | |
186 | vp->v_fifoinfo = NULL; | |
187 | return (error); | |
188 | } | |
189 | fip->fi_readsock = rso; | |
190 | if (error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) { | |
191 | (void)soclose(rso); | |
192 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
193 | _FREE_ZONE(fip, sizeof *fip, M_VNODE); | |
194 | vp->v_fifoinfo = NULL; | |
195 | return (error); | |
196 | } | |
197 | fip->fi_writesock = wso; | |
198 | if (error = unp_connect2(wso, rso)) { | |
199 | (void)soclose(wso); | |
200 | (void)soclose(rso); | |
201 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
202 | _FREE_ZONE(fip, sizeof *fip, M_VNODE); | |
203 | vp->v_fifoinfo = NULL; | |
204 | return (error); | |
205 | } | |
206 | wso->so_state |= SS_CANTRCVMORE; | |
207 | wso->so_snd.sb_lowat = PIPE_BUF; | |
208 | rso->so_state |= SS_CANTSENDMORE; | |
209 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
210 | fip->fi_readers = fip->fi_writers = 0; | |
211 | } | |
212 | if (ap->a_mode & FREAD) { | |
213 | fip->fi_readers++; | |
214 | if (fip->fi_readers == 1) { | |
215 | fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; | |
216 | if (fip->fi_writers > 0) | |
217 | wakeup((caddr_t)&fip->fi_writers); | |
218 | } | |
219 | } | |
220 | if (ap->a_mode & FWRITE) { | |
221 | fip->fi_writers++; | |
222 | if (fip->fi_writers == 1) { | |
223 | fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; | |
224 | if (fip->fi_readers > 0) | |
225 | wakeup((caddr_t)&fip->fi_readers); | |
226 | } | |
227 | } | |
228 | if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { | |
229 | if (fip->fi_writers == 0) { | |
230 | VOP_UNLOCK(vp, 0, p); | |
231 | error = tsleep((caddr_t)&fip->fi_readers, | |
232 | PCATCH | PSOCK, "fifoor", 0); | |
233 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); | |
234 | if (error) | |
235 | goto bad; | |
236 | if (fip->fi_readers == 1) { | |
237 | if (fip->fi_writers > 0) | |
238 | wakeup((caddr_t)&fip->fi_writers); | |
239 | } | |
240 | } | |
241 | } | |
242 | if (ap->a_mode & FWRITE) { | |
243 | if (ap->a_mode & O_NONBLOCK) { | |
244 | if (fip->fi_readers == 0) { | |
245 | error = ENXIO; | |
246 | goto bad; | |
247 | } | |
248 | } else { | |
249 | if (fip->fi_readers == 0) { | |
250 | VOP_UNLOCK(vp, 0, p); | |
251 | error = tsleep((caddr_t)&fip->fi_writers, | |
252 | PCATCH | PSOCK, "fifoow", 0); | |
253 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); | |
254 | if (error) | |
255 | goto bad; | |
256 | if (fip->fi_writers == 1) { | |
257 | if (fip->fi_readers > 0) | |
258 | wakeup((caddr_t)&fip->fi_readers); | |
259 | } | |
260 | } | |
261 | } | |
262 | } | |
263 | return (0); | |
264 | bad: | |
265 | if (error) | |
266 | VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p); | |
267 | return (error); | |
268 | } | |
269 | ||
270 | /* | |
271 | * Vnode op for read | |
272 | */ | |
273 | /* ARGSUSED */ | |
274 | fifo_read(ap) | |
275 | struct vop_read_args /* { | |
276 | struct vnode *a_vp; | |
277 | struct uio *a_uio; | |
278 | int a_ioflag; | |
279 | struct ucred *a_cred; | |
280 | } */ *ap; | |
281 | { | |
282 | struct uio *uio = ap->a_uio; | |
283 | struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; | |
284 | struct proc *p = uio->uio_procp; | |
285 | int error, startresid; | |
286 | ||
287 | #if DIAGNOSTIC | |
288 | if (uio->uio_rw != UIO_READ) | |
289 | panic("fifo_read mode"); | |
290 | #endif | |
291 | if (uio->uio_resid == 0) | |
292 | return (0); | |
293 | if (ap->a_ioflag & IO_NDELAY) | |
294 | rso->so_state |= SS_NBIO; | |
295 | startresid = uio->uio_resid; | |
296 | VOP_UNLOCK(ap->a_vp, 0, p); | |
297 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
298 | error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, | |
299 | (struct mbuf **)0, (int *)0); | |
300 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
301 | vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); | |
302 | /* | |
303 | * Clear EOF indication after first such return. | |
304 | */ | |
305 | if (uio->uio_resid == startresid) | |
306 | rso->so_state &= ~SS_CANTRCVMORE; | |
307 | if (ap->a_ioflag & IO_NDELAY) | |
308 | rso->so_state &= ~SS_NBIO; | |
309 | return (error); | |
310 | } | |
311 | ||
312 | /* | |
313 | * Vnode op for write | |
314 | */ | |
315 | /* ARGSUSED */ | |
316 | fifo_write(ap) | |
317 | struct vop_write_args /* { | |
318 | struct vnode *a_vp; | |
319 | struct uio *a_uio; | |
320 | int a_ioflag; | |
321 | struct ucred *a_cred; | |
322 | } */ *ap; | |
323 | { | |
324 | struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; | |
325 | struct proc *p = ap->a_uio->uio_procp; | |
326 | int error; | |
327 | ||
328 | #if DIAGNOSTIC | |
329 | if (ap->a_uio->uio_rw != UIO_WRITE) | |
330 | panic("fifo_write mode"); | |
331 | #endif | |
332 | if (ap->a_ioflag & IO_NDELAY) | |
333 | wso->so_state |= SS_NBIO; | |
334 | VOP_UNLOCK(ap->a_vp, 0, p); | |
335 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
336 | error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0, (struct mbuf *)0, 0); | |
337 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
338 | vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); | |
339 | if (ap->a_ioflag & IO_NDELAY) | |
340 | wso->so_state &= ~SS_NBIO; | |
341 | return (error); | |
342 | } | |
343 | ||
344 | /* | |
345 | * Device ioctl operation. | |
346 | */ | |
347 | /* ARGSUSED */ | |
348 | fifo_ioctl(ap) | |
349 | struct vop_ioctl_args /* { | |
350 | struct vnode *a_vp; | |
351 | int a_command; | |
352 | caddr_t a_data; | |
353 | int a_fflag; | |
354 | struct ucred *a_cred; | |
355 | struct proc *a_p; | |
356 | } */ *ap; | |
357 | { | |
358 | struct file filetmp; | |
359 | int error; | |
360 | ||
361 | if (ap->a_command == FIONBIO) | |
362 | return (0); | |
363 | if (ap->a_fflag & FREAD) { | |
364 | filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; | |
365 | error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); | |
366 | if (error) | |
367 | return (error); | |
368 | } | |
369 | if (ap->a_fflag & FWRITE) { | |
370 | filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; | |
371 | error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); | |
372 | if (error) | |
373 | return (error); | |
374 | } | |
375 | return (0); | |
376 | } | |
377 | ||
378 | /* ARGSUSED */ | |
379 | fifo_select(ap) | |
380 | struct vop_select_args /* { | |
381 | struct vnode *a_vp; | |
382 | int a_which; | |
383 | int a_fflags; | |
384 | struct ucred *a_cred; | |
0b4e3aa0 | 385 | void * a_wql; |
1c79356b A |
386 | struct proc *a_p; |
387 | } */ *ap; | |
388 | { | |
389 | struct file filetmp; | |
390 | int ready; | |
391 | ||
9bccf70c | 392 | if (ap->a_which & FREAD) { |
1c79356b | 393 | filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; |
0b4e3aa0 | 394 | ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_p); |
1c79356b A |
395 | if (ready) |
396 | return (ready); | |
397 | } | |
9bccf70c | 398 | if (ap->a_which & FWRITE) { |
1c79356b | 399 | filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; |
0b4e3aa0 | 400 | ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_p); |
1c79356b A |
401 | if (ready) |
402 | return (ready); | |
403 | } | |
404 | return (0); | |
405 | } | |
406 | ||
407 | int | |
408 | fifo_inactive(ap) | |
409 | struct vop_inactive_args /* { | |
410 | struct vnode *a_vp; | |
411 | struct proc *a_p; | |
412 | } */ *ap; | |
413 | { | |
414 | ||
415 | VOP_UNLOCK(ap->a_vp, 0, ap->a_p); | |
416 | return (0); | |
417 | } | |
418 | ||
419 | /* | |
420 | * This is a noop, simply returning what one has been given. | |
421 | */ | |
422 | fifo_bmap(ap) | |
423 | struct vop_bmap_args /* { | |
424 | struct vnode *a_vp; | |
425 | daddr_t a_bn; | |
426 | struct vnode **a_vpp; | |
427 | daddr_t *a_bnp; | |
428 | int *a_runp; | |
429 | } */ *ap; | |
430 | { | |
431 | ||
432 | if (ap->a_vpp != NULL) | |
433 | *ap->a_vpp = ap->a_vp; | |
434 | if (ap->a_bnp != NULL) | |
435 | *ap->a_bnp = ap->a_bn; | |
436 | if (ap->a_runp != NULL) | |
437 | *ap->a_runp = 0; | |
438 | return (0); | |
439 | } | |
440 | ||
441 | /* | |
442 | * Device close routine | |
443 | */ | |
444 | /* ARGSUSED */ | |
445 | fifo_close(ap) | |
446 | struct vop_close_args /* { | |
447 | struct vnode *a_vp; | |
448 | int a_fflag; | |
449 | struct ucred *a_cred; | |
450 | struct proc *a_p; | |
451 | } */ *ap; | |
452 | { | |
453 | register struct vnode *vp = ap->a_vp; | |
454 | register struct fifoinfo *fip = vp->v_fifoinfo; | |
455 | int error1, error2; | |
456 | ||
457 | if (ap->a_fflag & FREAD) { | |
458 | fip->fi_readers--; | |
459 | if (fip->fi_readers == 0){ | |
460 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
461 | socantsendmore(fip->fi_writesock); | |
462 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
463 | } | |
464 | } | |
465 | if (ap->a_fflag & FWRITE) { | |
466 | fip->fi_writers--; | |
467 | if (fip->fi_writers == 0) { | |
468 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
469 | socantrcvmore(fip->fi_readsock); | |
470 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
471 | } | |
472 | } | |
473 | if (vp->v_usecount > 1) | |
474 | return (0); | |
475 | thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); | |
476 | error1 = soclose(fip->fi_readsock); | |
477 | error2 = soclose(fip->fi_writesock); | |
478 | thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); | |
479 | FREE_ZONE(fip, sizeof *fip, M_VNODE); | |
480 | vp->v_fifoinfo = NULL; | |
481 | if (error1) | |
482 | return (error1); | |
483 | return (error2); | |
484 | } | |
485 | ||
486 | /* | |
487 | * Print out the contents of a fifo vnode. | |
488 | */ | |
489 | fifo_print(ap) | |
490 | struct vop_print_args /* { | |
491 | struct vnode *a_vp; | |
492 | } */ *ap; | |
493 | { | |
494 | ||
495 | printf("tag VT_NON"); | |
496 | fifo_printinfo(ap->a_vp); | |
497 | printf("\n"); | |
498 | } | |
499 | ||
500 | /* | |
501 | * Print out internal contents of a fifo vnode. | |
502 | */ | |
503 | fifo_printinfo(vp) | |
504 | struct vnode *vp; | |
505 | { | |
506 | register struct fifoinfo *fip = vp->v_fifoinfo; | |
507 | ||
508 | printf(", fifo with %d readers and %d writers", | |
509 | fip->fi_readers, fip->fi_writers); | |
510 | } | |
511 | ||
512 | /* | |
513 | * Return POSIX pathconf information applicable to fifo's. | |
514 | */ | |
515 | fifo_pathconf(ap) | |
516 | struct vop_pathconf_args /* { | |
517 | struct vnode *a_vp; | |
518 | int a_name; | |
519 | int *a_retval; | |
520 | } */ *ap; | |
521 | { | |
522 | ||
523 | switch (ap->a_name) { | |
524 | case _PC_LINK_MAX: | |
525 | *ap->a_retval = LINK_MAX; | |
526 | return (0); | |
527 | case _PC_PIPE_BUF: | |
528 | *ap->a_retval = PIPE_BUF; | |
529 | return (0); | |
530 | case _PC_CHOWN_RESTRICTED: | |
531 | *ap->a_retval = 1; | |
532 | return (0); | |
533 | default: | |
534 | return (EINVAL); | |
535 | } | |
536 | /* NOTREACHED */ | |
537 | } | |
538 | ||
539 | /* | |
540 | * Fifo failed operation | |
541 | */ | |
542 | fifo_ebadf() | |
543 | { | |
544 | ||
545 | return (EBADF); | |
546 | } | |
547 | ||
548 | /* | |
549 | * Fifo advisory byte-level locks. | |
550 | */ | |
551 | /* ARGSUSED */ | |
552 | fifo_advlock(ap) | |
553 | struct vop_advlock_args /* { | |
554 | struct vnode *a_vp; | |
555 | caddr_t a_id; | |
556 | int a_op; | |
557 | struct flock *a_fl; | |
558 | int a_flags; | |
559 | } */ *ap; | |
560 | { | |
561 | ||
562 | return (EOPNOTSUPP); | |
563 | } | |
564 |