386BSD 0.1 development
[unix-history] / usr / src / sys.386bsd / kern / fifo_vnops.c
CommitLineData
b688fc87
WJ
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 */
54struct fifoinfo {
55 struct socket *fi_readsock;
56 struct socket *fi_writesock;
57 long fi_readers;
58 long fi_writers;
59};
60
61struct 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 */
101fifo_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 */
117fifo_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 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
134 free(fip, M_VNODE);
135 vp->v_fifoinfo = NULL;
136 return (error);
137 }
138 fip->fi_readsock = rso;
139 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
140 (void)soclose(rso);
141 free(fip, M_VNODE);
142 vp->v_fifoinfo = NULL;
143 return (error);
144 }
145 fip->fi_writesock = wso;
146 if (error = unp_connect2(wso, rso)) {
147 (void)soclose(wso);
148 (void)soclose(rso);
149 free(fip, M_VNODE);
150 vp->v_fifoinfo = NULL;
151 return (error);
152 }
153 wso->so_state |= SS_CANTRCVMORE;
154 rso->so_state |= SS_CANTSENDMORE;
155 }
156 error = 0;
157 if (mode & FREAD) {
158 fip->fi_readers++;
159 if (fip->fi_readers == 1) {
160 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
161 if (fip->fi_writers > 0)
162 wakeup((caddr_t)&fip->fi_writers);
163 }
164 if (mode & O_NONBLOCK)
165 return (0);
166 while (fip->fi_writers == 0)
167 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
168 openstr, 0))
169 break;
170 } else {
171 fip->fi_writers++;
172 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
173 error = ENXIO;
174 } else {
175 if (fip->fi_writers == 1) {
176 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
177 if (fip->fi_readers > 0)
178 wakeup((caddr_t)&fip->fi_readers);
179 }
180 while (fip->fi_readers == 0)
181 if (error = tsleep((caddr_t)&fip->fi_writers,
182 PSOCK, openstr, 0))
183 break;
184 }
185 }
186 if (error)
187 fifo_close(vp, mode, cred, p);
188 return (error);
189}
190
191/*
192 * Vnode op for read
193 */
194/* ARGSUSED */
195fifo_read(vp, uio, ioflag, cred)
196 struct vnode *vp;
197 register struct uio *uio;
198 int ioflag;
199 struct ucred *cred;
200{
201 register struct socket *rso = vp->v_fifoinfo->fi_readsock;
202 int error, startresid;
203
204#ifdef DIAGNOSTIC
205 if (uio->uio_rw != UIO_READ)
206 panic("fifo_read mode");
207#endif
208 if (uio->uio_resid == 0)
209 return (0);
210 if (ioflag & IO_NDELAY)
211 rso->so_state |= SS_NBIO;
212 startresid = uio->uio_resid;
213 VOP_UNLOCK(vp);
214 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
215 (struct mbuf **)0, (struct mbuf **)0);
216 VOP_LOCK(vp);
217 /*
218 * Clear EOF indication after first such return.
219 */
220 if (uio->uio_resid == startresid)
221 rso->so_state &= ~SS_CANTRCVMORE;
222 if (ioflag & IO_NDELAY)
223 rso->so_state &= ~SS_NBIO;
224 return (error);
225}
226
227/*
228 * Vnode op for write
229 */
230/* ARGSUSED */
231fifo_write(vp, uio, ioflag, cred)
232 struct vnode *vp;
233 register struct uio *uio;
234 int ioflag;
235 struct ucred *cred;
236{
237 struct socket *wso = vp->v_fifoinfo->fi_writesock;
238 int error;
239
240#ifdef DIAGNOSTIC
241 if (uio->uio_rw != UIO_WRITE)
242 panic("fifo_write mode");
243#endif
244 if (ioflag & IO_NDELAY)
245 wso->so_state |= SS_NBIO;
246 VOP_UNLOCK(vp);
247 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
248 VOP_LOCK(vp);
249 if (ioflag & IO_NDELAY)
250 wso->so_state &= ~SS_NBIO;
251 return (error);
252}
253
254/*
255 * Device ioctl operation.
256 */
257/* ARGSUSED */
258fifo_ioctl(vp, com, data, fflag, cred, p)
259 struct vnode *vp;
260 int com;
261 caddr_t data;
262 int fflag;
263 struct ucred *cred;
264 struct proc *p;
265{
266 struct file filetmp;
267 int error;
268
269 if (com == FIONBIO)
270 return (0);
271 if (fflag & FREAD)
272 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
273 else
274 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
275 return (soo_ioctl(&filetmp, com, data, p));
276}
277
278/* ARGSUSED */
279fifo_select(vp, which, fflag, cred, p)
280 struct vnode *vp;
281 int which, fflag;
282 struct ucred *cred;
283 struct proc *p;
284{
285 struct file filetmp;
286 int error;
287
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_select(&filetmp, which, p));
293}
294
295/*
296 * This is a noop, simply returning what one has been given.
297 */
298fifo_bmap(vp, bn, vpp, bnp)
299 struct vnode *vp;
300 daddr_t bn;
301 struct vnode **vpp;
302 daddr_t *bnp;
303{
304
305 if (vpp != NULL)
306 *vpp = vp;
307 if (bnp != NULL)
308 *bnp = bn;
309 return (0);
310}
311
312/*
313 * At the moment we do not do any locking.
314 */
315/* ARGSUSED */
316fifo_lock(vp)
317 struct vnode *vp;
318{
319
320 return (0);
321}
322
323/* ARGSUSED */
324fifo_unlock(vp)
325 struct vnode *vp;
326{
327
328 return (0);
329}
330
331/*
332 * Device close routine
333 */
334/* ARGSUSED */
335fifo_close(vp, fflag, cred, p)
336 register struct vnode *vp;
337 int fflag;
338 struct ucred *cred;
339 struct proc *p;
340{
341 register struct fifoinfo *fip = vp->v_fifoinfo;
342 int error1, error2;
343
344 if (fflag & FWRITE) {
345 fip->fi_writers--;
346 if (fip->fi_writers == 0)
347 socantrcvmore(fip->fi_readsock);
348 } else {
349 fip->fi_readers--;
350 if (fip->fi_readers == 0)
351 socantsendmore(fip->fi_writesock);
352 }
353 if (vp->v_usecount > 1)
354 return (0);
355 error1 = soclose(fip->fi_readsock);
356 error2 = soclose(fip->fi_writesock);
357 FREE(fip, M_VNODE);
358 vp->v_fifoinfo = NULL;
359 if (error1)
360 return (error1);
361 return (error2);
362}
363
364/*
365 * Print out the contents of a fifo vnode.
366 */
367fifo_print(vp)
368 struct vnode *vp;
369{
370
371 printf("tag VT_NON");
372 fifo_printinfo(vp);
373 printf("\n");
374}
375
376/*
377 * Print out internal contents of a fifo vnode.
378 */
379fifo_printinfo(vp)
380 struct vnode *vp;
381{
382 register struct fifoinfo *fip = vp->v_fifoinfo;
383
384 printf(", fifo with %d readers and %d writers",
385 fip->fi_readers, fip->fi_writers);
386}
387
388/*
389 * Fifo failed operation
390 */
391fifo_ebadf()
392{
393
394 return (EBADF);
395}
396
397/*
398 * Fifo advisory byte-level locks.
399 */
400/* ARGSUSED */
401fifo_advlock(vp, id, op, fl, flags)
402 struct vnode *vp;
403 caddr_t id;
404 int op;
405 struct flock *fl;
406 int flags;
407{
408
409 return (EOPNOTSUPP);
410}
411
412/*
413 * Fifo bad operation
414 */
415fifo_badop()
416{
417
418 panic("fifo_badop called");
419 /* NOTREACHED */
420}