it's tsleep; it looks like this
[unix-history] / usr / src / sys / miscfs / fifofs / fifo_vnops.c
CommitLineData
cc6b488e
KM
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 are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
bcc829cc 17 * @(#)fifo_vnops.c 7.2 (Berkeley) %G%
cc6b488e
KM
18 */
19
20#include "param.h"
21#include "time.h"
22#include "namei.h"
23#include "vnode.h"
24#include "socket.h"
25#include "socketvar.h"
26#include "stat.h"
27#include "ioctl.h"
28#include "file.h"
29#include "errno.h"
30#include "malloc.h"
31
32/*
33 * This structure is associated with the FIFO vnode and stores
34 * the state associated with the FIFO.
35 */
36struct fifoinfo {
37 struct socket *fi_readsock;
38 struct socket *fi_writesock;
39 long fi_readers;
40 long fi_writers;
41};
42
43int fifo_lookup(),
44 fifo_open(),
45 fifo_read(),
46 fifo_write(),
47 fifo_strategy(),
48 fifo_bmap(),
49 fifo_ioctl(),
50 fifo_select(),
51 fifo_lock(),
52 fifo_unlock(),
53 fifo_close(),
54 fifo_print(),
55 fifo_ebadf(),
56 fifo_badop(),
57 fifo_nullop();
58
59struct vnodeops fifo_vnodeops = {
60 fifo_lookup, /* lookup */
61 fifo_badop, /* create */
62 fifo_badop, /* mknod */
63 fifo_open, /* open */
64 fifo_close, /* close */
65 fifo_ebadf, /* access */
66 fifo_ebadf, /* getattr */
67 fifo_ebadf, /* setattr */
68 fifo_read, /* read */
69 fifo_write, /* write */
70 fifo_ioctl, /* ioctl */
71 fifo_select, /* select */
72 fifo_badop, /* mmap */
73 fifo_nullop, /* fsync */
74 fifo_badop, /* seek */
75 fifo_badop, /* remove */
76 fifo_badop, /* link */
77 fifo_badop, /* rename */
78 fifo_badop, /* mkdir */
79 fifo_badop, /* rmdir */
80 fifo_badop, /* symlink */
81 fifo_badop, /* readdir */
82 fifo_badop, /* readlink */
83 fifo_badop, /* abortop */
84 fifo_nullop, /* inactive */
85 fifo_nullop, /* reclaim */
86 fifo_lock, /* lock */
87 fifo_unlock, /* unlock */
88 fifo_bmap, /* bmap */
89 fifo_badop, /* strategy */
90 fifo_print, /* print */
91 fifo_nullop, /* islocked */
92};
93
94/*
95 * Trivial lookup routine that always fails.
96 */
97fifo_lookup(vp, ndp)
98 struct vnode *vp;
99 struct nameidata *ndp;
100{
101
102 ndp->ni_dvp = vp;
103 ndp->ni_vp = NULL;
104 return (ENOTDIR);
105}
106
107/*
108 * Open called to set up a new instance of a fifo or
109 * to find an active instance of a fifo.
110 */
111/* ARGSUSED */
112fifo_open(vp, mode, cred)
113 register struct vnode *vp;
114 int mode;
115 struct ucred *cred;
116{
117 register struct fifoinfo *fip;
118 struct socket *rso, *wso;
119 int error;
bcc829cc 120 static char openstr[] = "fifo";
cc6b488e
KM
121
122 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
123 return (EINVAL);
124 if ((fip = vp->v_fifoinfo) == NULL) {
125 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
126 vp->v_fifoinfo = fip;
127 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
128 return (error);
129 fip->fi_readsock = rso;
130 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
131 (void)soclose(rso);
132 return (error);
133 }
134 fip->fi_writesock = wso;
135 if (error = unp_connect2(wso, rso)) {
136 (void)soclose(wso);
137 (void)soclose(rso);
138 return (error);
139 }
140 wso->so_state |= SS_CANTRCVMORE;
141 rso->so_state |= SS_CANTSENDMORE;
142 }
143 error = 0;
144 if (mode & FREAD) {
145 fip->fi_readers++;
146 if (fip->fi_readers == 1) {
147 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
148 if (fip->fi_writers > 0)
149 wakeup((caddr_t)&fip->fi_writers);
150 }
151 if (mode & O_NONBLOCK)
152 return (0);
153 while (fip->fi_writers == 0)
bcc829cc
MK
154 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
155 openstr, 0))
cc6b488e
KM
156 break;
157 } else {
158 fip->fi_writers++;
159 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
160 error = ENXIO;
161 } else {
162 if (fip->fi_writers == 1) {
163 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
164 if (fip->fi_readers > 0)
165 wakeup((caddr_t)&fip->fi_readers);
166 }
167 while (fip->fi_readers == 0)
bcc829cc
MK
168 if (error = tsleep((caddr_t)&fip->fi_writers,
169 PSOCK, openstr, 0))
cc6b488e
KM
170 break;
171 }
172 }
173 if (error)
174 fifo_close(vp, mode, cred);
175 return (error);
176}
177
178/*
179 * Vnode op for read
180 */
181/* ARGSUSED */
182fifo_read(vp, uio, ioflag, cred)
183 struct vnode *vp;
184 register struct uio *uio;
185 int ioflag;
186 struct ucred *cred;
187{
188 register struct socket *rso = vp->v_fifoinfo->fi_readsock;
189 int error, startresid;
190
191 if (uio->uio_rw != UIO_READ)
192 panic("fifo_read mode");
193 if (uio->uio_resid == 0)
194 return (0);
195 if (ioflag & IO_NDELAY)
196 rso->so_state |= SS_NBIO;
197 startresid = uio->uio_resid;
198 VOP_UNLOCK(vp);
199 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
200 (struct mbuf **)0, (struct mbuf **)0);
201 VOP_LOCK(vp);
202 /*
203 * Clear EOF indication after first such return.
204 */
205 if (uio->uio_resid == startresid)
206 rso->so_state &= ~SS_CANTRCVMORE;
207 if (ioflag & IO_NDELAY)
208 rso->so_state &= ~SS_NBIO;
209 return (error);
210}
211
212/*
213 * Vnode op for write
214 */
215/* ARGSUSED */
216fifo_write(vp, uio, ioflag, cred)
217 struct vnode *vp;
218 register struct uio *uio;
219 int ioflag;
220 struct ucred *cred;
221{
222 struct socket *wso = vp->v_fifoinfo->fi_writesock;
223 int error;
224
225 if (uio->uio_rw != UIO_WRITE)
226 panic("fifo_write mode");
227 if (ioflag & IO_NDELAY)
228 wso->so_state |= SS_NBIO;
229 VOP_UNLOCK(vp);
230 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
231 VOP_LOCK(vp);
232 if (ioflag & IO_NDELAY)
233 wso->so_state &= ~SS_NBIO;
234 return (error);
235}
236
237/*
238 * Device ioctl operation.
239 */
240/* ARGSUSED */
241fifo_ioctl(vp, com, data, fflag, cred)
242 struct vnode *vp;
243 int com;
244 caddr_t data;
245 int fflag;
246 struct ucred *cred;
247{
248 struct file filetmp;
249 int error;
250
251 if (com == FIONBIO)
252 return (0);
253 if (fflag & FREAD)
254 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
255 else
256 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
257 return (soo_ioctl(&filetmp, com, data));
258}
259
260/* ARGSUSED */
261fifo_select(vp, which, fflag, cred)
262 struct vnode *vp;
263 int which, fflag;
264 struct ucred *cred;
265{
266 struct file filetmp;
267 int error;
268
269 if (fflag & FREAD)
270 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
271 else
272 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
273 return (soo_select(&filetmp, which));
274}
275
276/*
277 * This is a noop, simply returning what one has been given.
278 */
279fifo_bmap(vp, bn, vpp, bnp)
280 struct vnode *vp;
281 daddr_t bn;
282 struct vnode **vpp;
283 daddr_t *bnp;
284{
285
286 if (vpp != NULL)
287 *vpp = vp;
288 if (bnp != NULL)
289 *bnp = bn;
290 return (0);
291}
292
293/*
294 * At the moment we do not do any locking.
295 */
296/* ARGSUSED */
297fifo_lock(vp)
298 struct vnode *vp;
299{
300
301 return (0);
302}
303
304/* ARGSUSED */
305fifo_unlock(vp)
306 struct vnode *vp;
307{
308
309 return (0);
310}
311
312/*
313 * Device close routine
314 */
315/* ARGSUSED */
316fifo_close(vp, fflag, cred)
317 register struct vnode *vp;
318 int fflag;
319 struct ucred *cred;
320{
321 register struct fifoinfo *fip = vp->v_fifoinfo;
322 int error1, error2;
323
324 if (fflag & FWRITE) {
325 fip->fi_writers--;
326 if (fip->fi_writers == 0)
327 socantrcvmore(fip->fi_readsock);
328 } else {
329 fip->fi_readers--;
330 if (fip->fi_readers == 0)
331 socantsendmore(fip->fi_writesock);
332 }
333 if (vp->v_usecount > 1)
334 return (0);
335 error1 = soclose(fip->fi_readsock);
336 error2 = soclose(fip->fi_writesock);
337 FREE(fip, M_VNODE);
338 vp->v_fifoinfo = NULL;
339 if (error1)
340 return (error1);
341 return (error2);
342}
343
344/*
345 * Print out the contents of a fifo vnode.
346 */
347fifo_print(vp)
348 struct vnode *vp;
349{
350
351 printf("tag VT_NON");
352 fifo_printinfo(vp);
353 printf("\n");
354}
355
356/*
357 * Print out internal contents of a fifo vnode.
358 */
359fifo_printinfo(vp)
360 struct vnode *vp;
361{
362 register struct fifoinfo *fip = vp->v_fifoinfo;
363
364 printf(", fifo with %d readers and %d writers",
365 fip->fi_readers, fip->fi_writers);
366}
367
368/*
369 * Fifo failed operation
370 */
371fifo_ebadf()
372{
373
374 return (EBADF);
375}
376
377/*
378 * Fifo bad operation
379 */
380fifo_badop()
381{
382
383 panic("fifo_badop called");
384 /* NOTREACHED */
385}
386
387/*
388 * Fifo null operation
389 */
390fifo_nullop()
391{
392
393 return (0);
394}