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