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