Annotation of src/sys/miscfs/fifofs/fifo_vnops.c, Revision 1.7
1.1 cgd 1: /*
2: * Copyright (c) 1990 The Regents of the University of California.
3: * 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: *
1.3 cgd 33: * from: @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91
1.7 ! cgd 34: * $Id: fifo_vnops.c,v 1.6 1993/12/18 03:49:25 mycroft Exp $
1.1 cgd 35: */
36:
1.6 mycroft 37: #include <sys/param.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/un.h>
44: #include <sys/stat.h>
45: #include <sys/systm.h>
46: #include <sys/ioctl.h>
47: #include <sys/file.h>
48: #include <sys/errno.h>
49: #include <sys/malloc.h>
50:
51: #include <miscfs/fifofs/fifo.h>
1.1 cgd 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: struct vnodeops fifo_vnodeops = {
65: fifo_lookup, /* lookup */
66: fifo_create, /* create */
67: fifo_mknod, /* mknod */
68: fifo_open, /* open */
69: fifo_close, /* close */
70: fifo_access, /* access */
71: fifo_getattr, /* getattr */
72: fifo_setattr, /* setattr */
73: fifo_read, /* read */
74: fifo_write, /* write */
75: fifo_ioctl, /* ioctl */
76: fifo_select, /* select */
77: fifo_mmap, /* mmap */
78: fifo_fsync, /* fsync */
79: fifo_seek, /* seek */
80: fifo_remove, /* remove */
81: fifo_link, /* link */
82: fifo_rename, /* rename */
83: fifo_mkdir, /* mkdir */
84: fifo_rmdir, /* rmdir */
85: fifo_symlink, /* symlink */
86: fifo_readdir, /* readdir */
87: fifo_readlink, /* readlink */
88: fifo_abortop, /* abortop */
89: fifo_inactive, /* inactive */
90: fifo_reclaim, /* reclaim */
91: fifo_lock, /* lock */
92: fifo_unlock, /* unlock */
93: fifo_bmap, /* bmap */
94: fifo_strategy, /* strategy */
95: fifo_print, /* print */
96: fifo_islocked, /* islocked */
97: fifo_advlock, /* advlock */
98: };
99:
100: /*
101: * Trivial lookup routine that always fails.
102: */
103: /* ARGSUSED */
1.5 andrew 104: int
1.1 cgd 105: fifo_lookup(vp, ndp, p)
106: struct vnode *vp;
107: struct nameidata *ndp;
108: struct proc *p;
109: {
110:
111: ndp->ni_dvp = vp;
112: ndp->ni_vp = NULL;
113: return (ENOTDIR);
114: }
115:
116: /*
117: * Open called to set up a new instance of a fifo or
118: * to find an active instance of a fifo.
119: */
120: /* ARGSUSED */
1.5 andrew 121: int
1.1 cgd 122: fifo_open(vp, mode, cred, p)
123: register struct vnode *vp;
124: int mode;
125: struct ucred *cred;
126: struct proc *p;
127: {
128: register struct fifoinfo *fip;
129: struct socket *rso, *wso;
130: int error;
131: static char openstr[] = "fifo";
132:
133: if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
134: return (EINVAL);
135: if ((fip = vp->v_fifoinfo) == NULL) {
136: MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
137: vp->v_fifoinfo = fip;
1.2 cgd 138: fip->fi_readers=0;
139: fip->fi_writers=0;
1.1 cgd 140: if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
141: free(fip, M_VNODE);
142: vp->v_fifoinfo = NULL;
143: return (error);
144: }
145: fip->fi_readsock = rso;
146: if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
147: (void)soclose(rso);
148: free(fip, M_VNODE);
149: vp->v_fifoinfo = NULL;
150: return (error);
151: }
152: fip->fi_writesock = wso;
153: if (error = unp_connect2(wso, rso)) {
154: (void)soclose(wso);
155: (void)soclose(rso);
156: free(fip, M_VNODE);
157: vp->v_fifoinfo = NULL;
158: return (error);
159: }
160: wso->so_state |= SS_CANTRCVMORE;
161: rso->so_state |= SS_CANTSENDMORE;
162: }
163: error = 0;
164: if (mode & FREAD) {
165: fip->fi_readers++;
166: if (fip->fi_readers == 1) {
167: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
168: if (fip->fi_writers > 0)
169: wakeup((caddr_t)&fip->fi_writers);
170: }
171: if (mode & O_NONBLOCK)
172: return (0);
1.2 cgd 173: while (fip->fi_writers == 0) {
174: VOP_UNLOCK(vp);
1.4 cgd 175: error = tsleep((caddr_t)&fip->fi_readers, PSOCK|PCATCH,
1.2 cgd 176: openstr, 0);
177: VOP_LOCK(vp);
178: if(error)
1.1 cgd 179: break;
1.2 cgd 180: }
1.1 cgd 181: } else {
182: fip->fi_writers++;
183: if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
184: error = ENXIO;
185: } else {
186: if (fip->fi_writers == 1) {
187: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
188: if (fip->fi_readers > 0)
189: wakeup((caddr_t)&fip->fi_readers);
190: }
1.2 cgd 191: while (fip->fi_readers == 0) {
192: VOP_UNLOCK(vp);
193: error = tsleep((caddr_t)&fip->fi_writers,
1.4 cgd 194: PSOCK|PCATCH, openstr, 0);
1.2 cgd 195: VOP_LOCK(vp);
196: if(error)
1.1 cgd 197: break;
1.2 cgd 198: }
1.1 cgd 199: }
200: }
201: if (error)
202: fifo_close(vp, mode, cred, p);
203: return (error);
204: }
205:
206: /*
207: * Vnode op for read
208: */
209: /* ARGSUSED */
1.5 andrew 210: int
1.1 cgd 211: fifo_read(vp, uio, ioflag, cred)
212: struct vnode *vp;
213: register struct uio *uio;
214: int ioflag;
215: struct ucred *cred;
216: {
217: register struct socket *rso = vp->v_fifoinfo->fi_readsock;
218: int error, startresid;
219:
220: #ifdef DIAGNOSTIC
221: if (uio->uio_rw != UIO_READ)
222: panic("fifo_read mode");
223: #endif
224: if (uio->uio_resid == 0)
225: return (0);
226: if (ioflag & IO_NDELAY)
227: rso->so_state |= SS_NBIO;
228: startresid = uio->uio_resid;
229: VOP_UNLOCK(vp);
1.5 andrew 230: error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
231: (struct mbuf **)0, (int *)0);
1.1 cgd 232: VOP_LOCK(vp);
233: /*
234: * Clear EOF indication after first such return.
235: */
236: if (uio->uio_resid == startresid)
237: rso->so_state &= ~SS_CANTRCVMORE;
238: if (ioflag & IO_NDELAY)
239: rso->so_state &= ~SS_NBIO;
240: return (error);
241: }
242:
243: /*
244: * Vnode op for write
245: */
246: /* ARGSUSED */
1.5 andrew 247: int
1.1 cgd 248: fifo_write(vp, uio, ioflag, cred)
249: struct vnode *vp;
250: register struct uio *uio;
251: int ioflag;
252: struct ucred *cred;
253: {
254: struct socket *wso = vp->v_fifoinfo->fi_writesock;
255: int error;
256:
257: #ifdef DIAGNOSTIC
258: if (uio->uio_rw != UIO_WRITE)
259: panic("fifo_write mode");
260: #endif
261: if (ioflag & IO_NDELAY)
262: wso->so_state |= SS_NBIO;
263: VOP_UNLOCK(vp);
1.5 andrew 264: error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0, 0);
1.1 cgd 265: VOP_LOCK(vp);
266: if (ioflag & IO_NDELAY)
267: wso->so_state &= ~SS_NBIO;
268: return (error);
269: }
270:
271: /*
272: * Device ioctl operation.
273: */
274: /* ARGSUSED */
1.5 andrew 275: int
1.1 cgd 276: fifo_ioctl(vp, com, data, fflag, cred, p)
277: struct vnode *vp;
278: int com;
279: caddr_t data;
280: int fflag;
281: struct ucred *cred;
282: struct proc *p;
283: {
284: struct file filetmp;
285:
286: if (com == FIONBIO)
287: return (0);
288: if (fflag & FREAD)
289: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
290: else
291: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
292: return (soo_ioctl(&filetmp, com, data, p));
293: }
294:
295: /* ARGSUSED */
1.5 andrew 296: int
1.1 cgd 297: fifo_select(vp, which, fflag, cred, p)
298: struct vnode *vp;
299: int which, fflag;
300: struct ucred *cred;
301: struct proc *p;
302: {
303: struct file filetmp;
304:
305: if (fflag & FREAD)
306: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
307: else
308: filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
309: return (soo_select(&filetmp, which, p));
310: }
311:
312: /*
313: * This is a noop, simply returning what one has been given.
314: */
1.5 andrew 315: int
1.1 cgd 316: fifo_bmap(vp, bn, vpp, bnp)
317: struct vnode *vp;
318: daddr_t bn;
319: struct vnode **vpp;
320: daddr_t *bnp;
321: {
322:
323: if (vpp != NULL)
324: *vpp = vp;
325: if (bnp != NULL)
326: *bnp = bn;
327: return (0);
328: }
329:
330: /*
331: * At the moment we do not do any locking.
332: */
333: /* ARGSUSED */
1.5 andrew 334: int
1.1 cgd 335: fifo_lock(vp)
336: struct vnode *vp;
337: {
338:
339: return (0);
340: }
341:
342: /* ARGSUSED */
1.5 andrew 343: int
1.1 cgd 344: fifo_unlock(vp)
345: struct vnode *vp;
346: {
347:
348: return (0);
349: }
350:
351: /*
352: * Device close routine
353: */
354: /* ARGSUSED */
1.5 andrew 355: int
1.1 cgd 356: fifo_close(vp, fflag, cred, p)
357: register struct vnode *vp;
358: int fflag;
359: struct ucred *cred;
360: struct proc *p;
361: {
362: register struct fifoinfo *fip = vp->v_fifoinfo;
363: int error1, error2;
364:
365: if (fflag & FWRITE) {
366: fip->fi_writers--;
367: if (fip->fi_writers == 0)
368: socantrcvmore(fip->fi_readsock);
369: } else {
370: fip->fi_readers--;
371: if (fip->fi_readers == 0)
372: socantsendmore(fip->fi_writesock);
373: }
374: if (vp->v_usecount > 1)
375: return (0);
376: error1 = soclose(fip->fi_readsock);
377: error2 = soclose(fip->fi_writesock);
378: FREE(fip, M_VNODE);
379: vp->v_fifoinfo = NULL;
380: if (error1)
381: return (error1);
382: return (error2);
383: }
384:
385: /*
386: * Print out the contents of a fifo vnode.
387: */
1.7 ! cgd 388: int
1.1 cgd 389: fifo_print(vp)
390: struct vnode *vp;
391: {
392:
393: printf("tag VT_NON");
394: fifo_printinfo(vp);
395: printf("\n");
1.7 ! cgd 396: return (0);
1.1 cgd 397: }
398:
399: /*
400: * Print out internal contents of a fifo vnode.
401: */
1.5 andrew 402: void
1.1 cgd 403: fifo_printinfo(vp)
404: struct vnode *vp;
405: {
406: register struct fifoinfo *fip = vp->v_fifoinfo;
407:
408: printf(", fifo with %d readers and %d writers",
409: fip->fi_readers, fip->fi_writers);
410: }
411:
412: /*
413: * Fifo failed operation
414: */
1.5 andrew 415: int
1.1 cgd 416: fifo_ebadf()
417: {
418:
419: return (EBADF);
420: }
421:
422: /*
423: * Fifo advisory byte-level locks.
424: */
425: /* ARGSUSED */
1.5 andrew 426: int
1.1 cgd 427: fifo_advlock(vp, id, op, fl, flags)
428: struct vnode *vp;
429: caddr_t id;
430: int op;
431: struct flock *fl;
432: int flags;
433: {
434:
435: return (EOPNOTSUPP);
436: }
437:
438: /*
439: * Fifo bad operation
440: */
1.5 andrew 441: int
1.1 cgd 442: fifo_badop()
443: {
444:
445: panic("fifo_badop called");
446: /* NOTREACHED */
447: }
CVSweb <webmaster@jp.NetBSD.org>