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