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