fifo_vnops.c revision 1.6 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 *
33 * from: @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91
34 * $Id: fifo_vnops.c,v 1.6 1993/12/18 03:49:25 mycroft Exp $
35 */
36
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>
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 */
104 int
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 */
121 int
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;
138 fip->fi_readers=0;
139 fip->fi_writers=0;
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);
173 while (fip->fi_writers == 0) {
174 VOP_UNLOCK(vp);
175 error = tsleep((caddr_t)&fip->fi_readers, PSOCK|PCATCH,
176 openstr, 0);
177 VOP_LOCK(vp);
178 if(error)
179 break;
180 }
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 }
191 while (fip->fi_readers == 0) {
192 VOP_UNLOCK(vp);
193 error = tsleep((caddr_t)&fip->fi_writers,
194 PSOCK|PCATCH, openstr, 0);
195 VOP_LOCK(vp);
196 if(error)
197 break;
198 }
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 */
210 int
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);
230 error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
231 (struct mbuf **)0, (int *)0);
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 */
247 int
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);
264 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0, 0);
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 */
275 int
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 */
296 int
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 */
315 int
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 */
334 int
335 fifo_lock(vp)
336 struct vnode *vp;
337 {
338
339 return (0);
340 }
341
342 /* ARGSUSED */
343 int
344 fifo_unlock(vp)
345 struct vnode *vp;
346 {
347
348 return (0);
349 }
350
351 /*
352 * Device close routine
353 */
354 /* ARGSUSED */
355 int
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 */
388 void
389 fifo_print(vp)
390 struct vnode *vp;
391 {
392
393 printf("tag VT_NON");
394 fifo_printinfo(vp);
395 printf("\n");
396 }
397
398 /*
399 * Print out internal contents of a fifo vnode.
400 */
401 void
402 fifo_printinfo(vp)
403 struct vnode *vp;
404 {
405 register struct fifoinfo *fip = vp->v_fifoinfo;
406
407 printf(", fifo with %d readers and %d writers",
408 fip->fi_readers, fip->fi_writers);
409 }
410
411 /*
412 * Fifo failed operation
413 */
414 int
415 fifo_ebadf()
416 {
417
418 return (EBADF);
419 }
420
421 /*
422 * Fifo advisory byte-level locks.
423 */
424 /* ARGSUSED */
425 int
426 fifo_advlock(vp, id, op, fl, flags)
427 struct vnode *vp;
428 caddr_t id;
429 int op;
430 struct flock *fl;
431 int flags;
432 {
433
434 return (EOPNOTSUPP);
435 }
436
437 /*
438 * Fifo bad operation
439 */
440 int
441 fifo_badop()
442 {
443
444 panic("fifo_badop called");
445 /* NOTREACHED */
446 }
447