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