xref: /netbsd-src/sys/miscfs/fifofs/fifo_vnops.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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