Annotation of sys/miscfs/fifofs/fifo_vnops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: fifo_vnops.c,v 1.24 2007/06/18 08:30:07 jasper Exp $ */
2: /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)fifo_vnops.c 8.4 (Berkeley) 8/10/94
33: */
34:
35: #include <sys/param.h>
36: #include <sys/proc.h>
37: #include <sys/systm.h>
38: #include <sys/time.h>
39: #include <sys/namei.h>
40: #include <sys/vnode.h>
41: #include <sys/socket.h>
42: #include <sys/socketvar.h>
43: #include <sys/stat.h>
44: #include <sys/ioctl.h>
45: #include <sys/file.h>
46: #include <sys/event.h>
47: #include <sys/errno.h>
48: #include <sys/malloc.h>
49: #include <sys/poll.h>
50: #include <sys/un.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)(void *);
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_poll_desc, fifo_poll }, /* poll */
79: { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */
80: { &vop_revoke_desc, fifo_revoke }, /* revoke */
81: { &vop_fsync_desc, fifo_fsync }, /* fsync */
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_bwrite_desc, fifo_bwrite }, /* bwrite */
102: { NULL, NULL }
103: };
104:
105: struct vnodeopv_desc fifo_vnodeop_opv_desc =
106: { &fifo_vnodeop_p, fifo_vnodeop_entries };
107:
108: int
109: fifo_vnoperate(void *v)
110: {
111: struct vop_generic_args *ap = v;
112:
113: return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
114: }
115:
116: void filt_fifordetach(struct knote *kn);
117: int filt_fiforead(struct knote *kn, long hint);
118: void filt_fifowdetach(struct knote *kn);
119: int filt_fifowrite(struct knote *kn, long hint);
120:
121: struct filterops fiforead_filtops =
122: { 1, NULL, filt_fifordetach, filt_fiforead };
123: struct filterops fifowrite_filtops =
124: { 1, NULL, filt_fifowdetach, filt_fifowrite };
125:
126: /*
127: * Trivial lookup routine that always fails.
128: */
129: /* ARGSUSED */
130: int
131: fifo_lookup(void *v)
132: {
133: struct vop_lookup_args *ap = v;
134:
135: *ap->a_vpp = NULL;
136: return (ENOTDIR);
137: }
138:
139: /*
140: * Open called to set up a new instance of a fifo or
141: * to find an active instance of a fifo.
142: */
143: /* ARGSUSED */
144: int
145: fifo_open(void *v)
146: {
147: struct vop_open_args *ap = v;
148: struct vnode *vp = ap->a_vp;
149: struct fifoinfo *fip;
150: struct proc *p = ap->a_p;
151: struct socket *rso, *wso;
152: int error;
153:
154: if ((fip = vp->v_fifoinfo) == NULL) {
155: MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
156: vp->v_fifoinfo = fip;
157: if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
158: free(fip, M_VNODE);
159: vp->v_fifoinfo = NULL;
160: return (error);
161: }
162: fip->fi_readsock = rso;
163: if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
164: (void)soclose(rso);
165: free(fip, M_VNODE);
166: vp->v_fifoinfo = NULL;
167: return (error);
168: }
169: fip->fi_writesock = wso;
170: if ((error = unp_connect2(wso, rso)) != 0) {
171: (void)soclose(wso);
172: (void)soclose(rso);
173: free(fip, M_VNODE);
174: vp->v_fifoinfo = NULL;
175: return (error);
176: }
177: fip->fi_readers = fip->fi_writers = 0;
178: wso->so_snd.sb_lowat = PIPE_BUF;
179: rso->so_state |= SS_CANTRCVMORE;
180: }
181: if (ap->a_mode & FREAD) {
182: fip->fi_readers++;
183: if (fip->fi_readers == 1) {
184: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
185: if (fip->fi_writers > 0)
186: wakeup(&fip->fi_writers);
187: }
188: }
189: if (ap->a_mode & FWRITE) {
190: fip->fi_writers++;
191: if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
192: error = ENXIO;
193: goto bad;
194: }
195: if (fip->fi_writers == 1) {
196: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
197: if (fip->fi_readers > 0)
198: wakeup(&fip->fi_readers);
199: }
200: }
201: if ((ap->a_mode & O_NONBLOCK) == 0) {
202: if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
203: VOP_UNLOCK(vp, 0, p);
204: error = tsleep(&fip->fi_readers,
205: PCATCH | PSOCK, "fifor", 0);
206: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
207: if (error)
208: goto bad;
209: }
210: if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
211: VOP_UNLOCK(vp, 0, p);
212: error = tsleep(&fip->fi_writers,
213: PCATCH | PSOCK, "fifow", 0);
214: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
215: if (error)
216: goto bad;
217: }
218: }
219: return (0);
220: bad:
221: VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
222: return (error);
223: }
224:
225: /*
226: * Vnode op for read
227: */
228: /* ARGSUSED */
229: int
230: fifo_read(void *v)
231: {
232: struct vop_read_args *ap = v;
233: struct uio *uio = ap->a_uio;
234: struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
235: struct proc *p = uio->uio_procp;
236: int error;
237:
238: #ifdef DIAGNOSTIC
239: if (uio->uio_rw != UIO_READ)
240: panic("fifo_read mode");
241: #endif
242: if (uio->uio_resid == 0)
243: return (0);
244: if (ap->a_ioflag & IO_NDELAY)
245: rso->so_state |= SS_NBIO;
246: VOP_UNLOCK(ap->a_vp, 0, p);
247: error = soreceive(rso, NULL, uio, NULL, NULL, NULL);
248: vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
249: if (ap->a_ioflag & IO_NDELAY) {
250: rso->so_state &= ~SS_NBIO;
251: if (error == EWOULDBLOCK &&
252: ap->a_vp->v_fifoinfo->fi_writers == 0)
253: error = 0;
254: }
255: return (error);
256: }
257:
258: /*
259: * Vnode op for write
260: */
261: /* ARGSUSED */
262: int
263: fifo_write(void *v)
264: {
265: struct vop_write_args *ap = v;
266: struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
267: struct proc *p = ap->a_uio->uio_procp;
268: int error;
269:
270: #ifdef DIAGNOSTIC
271: if (ap->a_uio->uio_rw != UIO_WRITE)
272: panic("fifo_write mode");
273: #endif
274: if (ap->a_ioflag & IO_NDELAY)
275: wso->so_state |= SS_NBIO;
276: VOP_UNLOCK(ap->a_vp, 0, p);
277: error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
278: vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
279: if (ap->a_ioflag & IO_NDELAY)
280: wso->so_state &= ~SS_NBIO;
281: return (error);
282: }
283:
284: /*
285: * Device ioctl operation.
286: */
287: /* ARGSUSED */
288: int
289: fifo_ioctl(void *v)
290: {
291: struct vop_ioctl_args *ap = v;
292: struct file filetmp;
293: int error;
294:
295: if (ap->a_command == FIONBIO)
296: return (0);
297: if (ap->a_fflag & FREAD) {
298: filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
299: error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
300: if (error)
301: return (error);
302: }
303: if (ap->a_fflag & FWRITE) {
304: filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
305: error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
306: if (error)
307: return (error);
308: }
309: return (0);
310: }
311:
312: /* ARGSUSED */
313: int
314: fifo_poll(void *v)
315: {
316: struct vop_poll_args *ap = v;
317: struct file filetmp;
318: short ostate;
319: int revents = 0;
320:
321: if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
322: /*
323: * Socket and FIFO poll(2) semantics differ wrt EOF on read.
324: * Unlike a normal socket, FIFOs don't care whether or not
325: * SS_CANTRCVMORE is set. To get the correct semantics we
326: * must clear SS_CANTRCVMORE from so_state temporarily.
327: */
328: ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
329: if (ap->a_events & (POLLIN | POLLRDNORM))
330: ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
331: ~SS_CANTRCVMORE;
332: filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
333: if (filetmp.f_data)
334: revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
335: ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
336: }
337: if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
338: filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
339: if (filetmp.f_data)
340: revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
341: }
342: return (revents);
343: }
344:
345: int
346: fifo_inactive(void *v)
347: {
348: struct vop_inactive_args *ap = v;
349:
350: VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
351: return (0);
352: }
353:
354: /*
355: * This is a noop, simply returning what one has been given.
356: */
357: int
358: fifo_bmap(void *v)
359: {
360: struct vop_bmap_args *ap = v;
361:
362: if (ap->a_vpp != NULL)
363: *ap->a_vpp = ap->a_vp;
364: if (ap->a_bnp != NULL)
365: *ap->a_bnp = ap->a_bn;
366: return (0);
367: }
368:
369: /*
370: * Device close routine
371: */
372: /* ARGSUSED */
373: int
374: fifo_close(void *v)
375: {
376: struct vop_close_args *ap = v;
377: struct vnode *vp = ap->a_vp;
378: struct fifoinfo *fip = vp->v_fifoinfo;
379: int error1 = 0, error2 = 0;
380:
381: if (fip == NULL)
382: return (0);
383:
384: if (ap->a_fflag & FREAD) {
385: if (--fip->fi_readers == 0)
386: socantsendmore(fip->fi_writesock);
387: }
388: if (ap->a_fflag & FWRITE) {
389: if (--fip->fi_writers == 0)
390: socantrcvmore(fip->fi_readsock);
391: }
392: if (fip->fi_readers == 0 && fip->fi_writers == 0) {
393: error1 = soclose(fip->fi_readsock);
394: error2 = soclose(fip->fi_writesock);
395: FREE(fip, M_VNODE);
396: vp->v_fifoinfo = NULL;
397: }
398: return (error1 ? error1 : error2);
399: }
400:
401: int
402: fifo_reclaim(void *v)
403: {
404: struct vop_reclaim_args *ap = v;
405: struct vnode *vp = ap->a_vp;
406: struct fifoinfo *fip = vp->v_fifoinfo;
407:
408: if (fip == NULL)
409: return (0);
410:
411: soclose(fip->fi_readsock);
412: soclose(fip->fi_writesock);
413: FREE(fip, M_VNODE);
414: vp->v_fifoinfo = NULL;
415:
416: return (0);
417: }
418:
419: /*
420: * Print out the contents of a fifo vnode.
421: */
422: int
423: fifo_print(void *v)
424: {
425: struct vop_print_args *ap = v;
426:
427: printf("tag VT_NON");
428: fifo_printinfo(ap->a_vp);
429: printf("\n");
430: return 0;
431: }
432:
433: /*
434: * Print out internal contents of a fifo vnode.
435: */
436: void
437: fifo_printinfo(struct vnode *vp)
438: {
439: struct fifoinfo *fip = vp->v_fifoinfo;
440:
441: printf(", fifo with %ld readers and %ld writers",
442: fip->fi_readers, fip->fi_writers);
443: }
444:
445: /*
446: * Return POSIX pathconf information applicable to fifo's.
447: */
448: int
449: fifo_pathconf(void *v)
450: {
451: struct vop_pathconf_args *ap = v;
452:
453: switch (ap->a_name) {
454: case _PC_LINK_MAX:
455: *ap->a_retval = LINK_MAX;
456: return (0);
457: case _PC_PIPE_BUF:
458: *ap->a_retval = PIPE_BUF;
459: return (0);
460: case _PC_CHOWN_RESTRICTED:
461: *ap->a_retval = 1;
462: return (0);
463: default:
464: return (EINVAL);
465: }
466: /* NOTREACHED */
467: }
468:
469: /*
470: * Fifo failed operation
471: */
472: /*ARGSUSED*/
473: int
474: fifo_ebadf(void *v)
475: {
476:
477: return (EBADF);
478: }
479:
480: /*
481: * Fifo advisory byte-level locks.
482: */
483: /* ARGSUSED */
484: int
485: fifo_advlock(void *v)
486: {
487: return (EOPNOTSUPP);
488: }
489:
490: /*
491: * Fifo bad operation
492: */
493: /*ARGSUSED*/
494: int
495: fifo_badop(void *v)
496: {
497:
498: panic("fifo_badop called");
499: /* NOTREACHED */
500: return(0);
501: }
502:
503:
504: int
505: fifo_kqfilter(void *v)
506: {
507: struct vop_kqfilter_args *ap = v;
508: struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
509: struct sockbuf *sb;
510:
511: switch (ap->a_kn->kn_filter) {
512: case EVFILT_READ:
513: ap->a_kn->kn_fop = &fiforead_filtops;
514: sb = &so->so_rcv;
515: break;
516: case EVFILT_WRITE:
517: ap->a_kn->kn_fop = &fifowrite_filtops;
518: sb = &so->so_snd;
519: break;
520: default:
521: return (1);
522: }
523:
524: ap->a_kn->kn_hook = so;
525:
526: SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
527: sb->sb_flags |= SB_KNOTE;
528:
529: return (0);
530: }
531:
532: void
533: filt_fifordetach(struct knote *kn)
534: {
535: struct socket *so = (struct socket *)kn->kn_hook;
536:
537: SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
538: if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
539: so->so_rcv.sb_flags &= ~SB_KNOTE;
540: }
541:
542: int
543: filt_fiforead(struct knote *kn, long hint)
544: {
545: struct socket *so = (struct socket *)kn->kn_hook;
546:
547: kn->kn_data = so->so_rcv.sb_cc;
548: if (so->so_state & SS_CANTRCVMORE) {
549: kn->kn_flags |= EV_EOF;
550: return (1);
551: }
552: kn->kn_flags &= ~EV_EOF;
553: return (kn->kn_data > 0);
554: }
555:
556: void
557: filt_fifowdetach(struct knote *kn)
558: {
559: struct socket *so = (struct socket *)kn->kn_hook;
560:
561: SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
562: if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
563: so->so_snd.sb_flags &= ~SB_KNOTE;
564: }
565:
566: int
567: filt_fifowrite(struct knote *kn, long hint)
568: {
569: struct socket *so = (struct socket *)kn->kn_hook;
570:
571: kn->kn_data = sbspace(&so->so_snd);
572: if (so->so_state & SS_CANTSENDMORE) {
573: kn->kn_flags |= EV_EOF;
574: return (1);
575: }
576: kn->kn_flags &= ~EV_EOF;
577: return (kn->kn_data >= so->so_snd.sb_lowat);
578: }
CVSweb