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