xref: /openbsd/sys/miscfs/fifofs/fifo_vnops.c (revision 898184e3)
1 /*	$OpenBSD: fifo_vnops.c,v 1.37 2012/06/20 17:30:22 matthew Exp $	*/
2 /*	$NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	@(#)fifo_vnops.c	8.4 (Berkeley) 8/10/94
33  */
34 
35 #include <sys/param.h>
36 #include <sys/proc.h>
37 #include <sys/systm.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/stat.h>
44 #include <sys/ioctl.h>
45 #include <sys/file.h>
46 #include <sys/event.h>
47 #include <sys/errno.h>
48 #include <sys/malloc.h>
49 #include <sys/poll.h>
50 #include <sys/un.h>
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 vops fifo_vops = {
65 	.vop_lookup	= vop_generic_lookup,
66 	.vop_create	= fifo_badop,
67 	.vop_mknod	= fifo_badop,
68 	.vop_open	= fifo_open,
69 	.vop_close	= fifo_close,
70 	.vop_access	= fifo_ebadf,
71 	.vop_getattr	= fifo_ebadf,
72 	.vop_setattr	= fifo_ebadf,
73 	.vop_read	= fifo_read,
74 	.vop_write	= fifo_write,
75 	.vop_ioctl	= fifo_ioctl,
76 	.vop_poll	= fifo_poll,
77 	.vop_kqfilter	= fifo_kqfilter,
78 	.vop_revoke	= vop_generic_revoke,
79 	.vop_fsync	= nullop,
80 	.vop_remove	= fifo_badop,
81 	.vop_link	= fifo_badop,
82 	.vop_rename	= fifo_badop,
83 	.vop_mkdir	= fifo_badop,
84 	.vop_rmdir	= fifo_badop,
85 	.vop_symlink	= fifo_badop,
86 	.vop_readdir	= fifo_badop,
87 	.vop_readlink	= fifo_badop,
88 	.vop_abortop	= fifo_badop,
89 	.vop_inactive	= fifo_inactive,
90 	.vop_reclaim	= fifo_reclaim,
91 	.vop_lock	= vop_generic_lock,
92 	.vop_unlock	= vop_generic_unlock,
93 	.vop_bmap	= vop_generic_bmap,
94 	.vop_strategy	= fifo_badop,
95 	.vop_print	= fifo_print,
96 	.vop_islocked	= vop_generic_islocked,
97 	.vop_pathconf	= fifo_pathconf,
98 	.vop_advlock	= fifo_advlock,
99 	.vop_bwrite	= nullop
100 };
101 
102 void	filt_fifordetach(struct knote *kn);
103 int	filt_fiforead(struct knote *kn, long hint);
104 void	filt_fifowdetach(struct knote *kn);
105 int	filt_fifowrite(struct knote *kn, long hint);
106 
107 struct filterops fiforead_filtops =
108 	{ 1, NULL, filt_fifordetach, filt_fiforead };
109 struct filterops fifowrite_filtops =
110 	{ 1, NULL, filt_fifowdetach, filt_fifowrite };
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 int
118 fifo_open(void *v)
119 {
120 	struct vop_open_args *ap = v;
121 	struct vnode *vp = ap->a_vp;
122 	struct fifoinfo *fip;
123 	struct proc *p = ap->a_p;
124 	struct socket *rso, *wso;
125 	int error;
126 
127 	if ((fip = vp->v_fifoinfo) == NULL) {
128 		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
129 		vp->v_fifoinfo = fip;
130 		if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
131 			free(fip, M_VNODE);
132 			vp->v_fifoinfo = NULL;
133 			return (error);
134 		}
135 		fip->fi_readsock = rso;
136 		if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
137 			(void)soclose(rso);
138 			free(fip, M_VNODE);
139 			vp->v_fifoinfo = NULL;
140 			return (error);
141 		}
142 		fip->fi_writesock = wso;
143 		if ((error = unp_connect2(wso, rso)) != 0) {
144 			(void)soclose(wso);
145 			(void)soclose(rso);
146 			free(fip, M_VNODE);
147 			vp->v_fifoinfo = NULL;
148 			return (error);
149 		}
150 		fip->fi_readers = fip->fi_writers = 0;
151 		wso->so_snd.sb_lowat = PIPE_BUF;
152 		rso->so_state |= SS_CANTRCVMORE;
153 	}
154 	if (ap->a_mode & FREAD) {
155 		fip->fi_readers++;
156 		if (fip->fi_readers == 1) {
157 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
158 			if (fip->fi_writers > 0)
159 				wakeup(&fip->fi_writers);
160 		}
161 	}
162 	if (ap->a_mode & FWRITE) {
163 		fip->fi_writers++;
164 		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
165 			error = ENXIO;
166 			goto bad;
167 		}
168 		if (fip->fi_writers == 1) {
169 			fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
170 			if (fip->fi_readers > 0)
171 				wakeup(&fip->fi_readers);
172 		}
173 	}
174 	if ((ap->a_mode & O_NONBLOCK) == 0) {
175 		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
176 			VOP_UNLOCK(vp, 0, p);
177 			error = tsleep(&fip->fi_readers,
178 			    PCATCH | PSOCK, "fifor", 0);
179 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
180 			if (error)
181 				goto bad;
182 		}
183 		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
184 			VOP_UNLOCK(vp, 0, p);
185 			error = tsleep(&fip->fi_writers,
186 			    PCATCH | PSOCK, "fifow", 0);
187 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
188 			if (error)
189 				goto bad;
190 		}
191 	}
192 	return (0);
193 bad:
194 	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
195 	return (error);
196 }
197 
198 /*
199  * Vnode op for read
200  */
201 /* ARGSUSED */
202 int
203 fifo_read(void *v)
204 {
205 	struct vop_read_args *ap = v;
206 	struct uio *uio = ap->a_uio;
207 	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
208 	struct proc *p = uio->uio_procp;
209 	int error;
210 
211 #ifdef DIAGNOSTIC
212 	if (uio->uio_rw != UIO_READ)
213 		panic("fifo_read mode");
214 #endif
215 	if (uio->uio_resid == 0)
216 		return (0);
217 	if (ap->a_ioflag & IO_NDELAY)
218 		rso->so_state |= SS_NBIO;
219 	VOP_UNLOCK(ap->a_vp, 0, p);
220 	error = soreceive(rso, NULL, uio, NULL, NULL, NULL, 0);
221 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
222 	if (ap->a_ioflag & IO_NDELAY) {
223 		rso->so_state &= ~SS_NBIO;
224 		if (error == EWOULDBLOCK &&
225 		    ap->a_vp->v_fifoinfo->fi_writers == 0)
226 			error = 0;
227 	}
228 	return (error);
229 }
230 
231 /*
232  * Vnode op for write
233  */
234 /* ARGSUSED */
235 int
236 fifo_write(void *v)
237 {
238 	struct vop_write_args *ap = v;
239 	struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
240 	struct proc *p = ap->a_uio->uio_procp;
241 	int error;
242 
243 #ifdef DIAGNOSTIC
244 	if (ap->a_uio->uio_rw != UIO_WRITE)
245 		panic("fifo_write mode");
246 #endif
247 	if (ap->a_ioflag & IO_NDELAY)
248 		wso->so_state |= SS_NBIO;
249 	VOP_UNLOCK(ap->a_vp, 0, p);
250 	error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
251 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
252 	if (ap->a_ioflag & IO_NDELAY)
253 		wso->so_state &= ~SS_NBIO;
254 	return (error);
255 }
256 
257 /*
258  * Device ioctl operation.
259  */
260 /* ARGSUSED */
261 int
262 fifo_ioctl(void *v)
263 {
264 	struct vop_ioctl_args *ap = v;
265 	struct file filetmp;
266 	int error;
267 
268 	if (ap->a_command == FIONBIO)
269 		return (0);
270 	if (ap->a_fflag & FREAD) {
271 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
272 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
273 		if (error)
274 			return (error);
275 	}
276 	if (ap->a_fflag & FWRITE) {
277 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
278 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
279 		if (error)
280 			return (error);
281 	}
282 	return (0);
283 }
284 
285 /* ARGSUSED */
286 int
287 fifo_poll(void *v)
288 {
289 	struct vop_poll_args *ap = v;
290 	struct file filetmp;
291 	short ostate;
292 	int revents = 0;
293 
294 	if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
295 		/*
296 		 * Socket and FIFO poll(2) semantics differ wrt EOF on read.
297 		 * Unlike a normal socket, FIFOs don't care whether or not
298 		 * SS_CANTRCVMORE is set.  To get the correct semantics we
299 		 * must clear SS_CANTRCVMORE from so_state temporarily.
300 		 */
301 		ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
302 		if (ap->a_events & (POLLIN | POLLRDNORM))
303 			ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
304 			    ~SS_CANTRCVMORE;
305 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
306 		if (filetmp.f_data)
307 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
308 		ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
309 	}
310 	if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
311 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
312 		if (filetmp.f_data)
313 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
314 	}
315 	return (revents);
316 }
317 
318 int
319 fifo_inactive(void *v)
320 {
321 	struct vop_inactive_args *ap = v;
322 
323 	VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
324 	return (0);
325 }
326 
327 
328 /*
329  * Device close routine
330  */
331 /* ARGSUSED */
332 int
333 fifo_close(void *v)
334 {
335 	struct vop_close_args *ap = v;
336 	struct vnode *vp = ap->a_vp;
337 	struct fifoinfo *fip = vp->v_fifoinfo;
338 	int error1 = 0, error2 = 0;
339 
340 	if (fip == NULL)
341 		return (0);
342 
343 	if (ap->a_fflag & FREAD) {
344 		if (--fip->fi_readers == 0)
345 			socantsendmore(fip->fi_writesock);
346 	}
347 	if (ap->a_fflag & FWRITE) {
348 		if (--fip->fi_writers == 0)
349 			socantrcvmore(fip->fi_readsock);
350 	}
351 	if (fip->fi_readers == 0 && fip->fi_writers == 0) {
352 		error1 = soclose(fip->fi_readsock);
353 		error2 = soclose(fip->fi_writesock);
354 		free(fip, M_VNODE);
355 		vp->v_fifoinfo = NULL;
356 	}
357 	return (error1 ? error1 : error2);
358 }
359 
360 int
361 fifo_reclaim(void *v)
362 {
363 	struct vop_reclaim_args *ap = v;
364 	struct vnode *vp = ap->a_vp;
365 	struct fifoinfo *fip = vp->v_fifoinfo;
366 
367 	if (fip == NULL)
368 		return (0);
369 
370 	soclose(fip->fi_readsock);
371 	soclose(fip->fi_writesock);
372 	free(fip, M_VNODE);
373 	vp->v_fifoinfo = NULL;
374 
375 	return (0);
376 }
377 
378 /*
379  * Print out the contents of a fifo vnode.
380  */
381 int
382 fifo_print(void *v)
383 {
384 	struct vop_print_args *ap = v;
385 
386 	printf("tag VT_NON");
387 	fifo_printinfo(ap->a_vp);
388 	printf("\n");
389 	return 0;
390 }
391 
392 /*
393  * Print out internal contents of a fifo vnode.
394  */
395 void
396 fifo_printinfo(struct vnode *vp)
397 {
398 	struct fifoinfo *fip = vp->v_fifoinfo;
399 
400 	printf(", fifo with %ld readers and %ld writers",
401 		fip->fi_readers, fip->fi_writers);
402 }
403 
404 /*
405  * Return POSIX pathconf information applicable to fifo's.
406  */
407 int
408 fifo_pathconf(void *v)
409 {
410 	struct vop_pathconf_args *ap = v;
411 	int error = 0;
412 
413 	switch (ap->a_name) {
414 	case _PC_LINK_MAX:
415 		*ap->a_retval = LINK_MAX;
416 		break;
417 	case _PC_PIPE_BUF:
418 		*ap->a_retval = PIPE_BUF;
419 		break;
420 	case _PC_CHOWN_RESTRICTED:
421 		*ap->a_retval = 1;
422 		break;
423 	default:
424 		error = EINVAL;
425 		break;
426 	}
427 
428 	return (error);
429 }
430 
431 /*
432  * Fifo failed operation
433  */
434 /*ARGSUSED*/
435 int
436 fifo_ebadf(void *v)
437 {
438 
439 	return (EBADF);
440 }
441 
442 /*
443  * Fifo advisory byte-level locks.
444  */
445 /* ARGSUSED */
446 int
447 fifo_advlock(void *v)
448 {
449 	return (EOPNOTSUPP);
450 }
451 
452 /*
453  * Fifo bad operation
454  */
455 /*ARGSUSED*/
456 int
457 fifo_badop(void *v)
458 {
459 
460 	panic("fifo_badop called");
461 	/* NOTREACHED */
462 	return(0);
463 }
464 
465 
466 int
467 fifo_kqfilter(void *v)
468 {
469 	struct vop_kqfilter_args *ap = v;
470 	struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
471 	struct sockbuf *sb;
472 
473 	switch (ap->a_kn->kn_filter) {
474 	case EVFILT_READ:
475 		ap->a_kn->kn_fop = &fiforead_filtops;
476 		sb = &so->so_rcv;
477 		break;
478 	case EVFILT_WRITE:
479 		ap->a_kn->kn_fop = &fifowrite_filtops;
480 		sb = &so->so_snd;
481 		break;
482 	default:
483 		return (EINVAL);
484 	}
485 
486 	ap->a_kn->kn_hook = so;
487 
488 	SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
489 	sb->sb_flags |= SB_KNOTE;
490 
491 	return (0);
492 }
493 
494 void
495 filt_fifordetach(struct knote *kn)
496 {
497 	struct socket *so = (struct socket *)kn->kn_hook;
498 
499 	SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
500 	if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
501 		so->so_rcv.sb_flags &= ~SB_KNOTE;
502 }
503 
504 int
505 filt_fiforead(struct knote *kn, long hint)
506 {
507 	struct socket *so = (struct socket *)kn->kn_hook;
508 
509 	kn->kn_data = so->so_rcv.sb_cc;
510 	if (so->so_state & SS_CANTRCVMORE) {
511 		kn->kn_flags |= EV_EOF;
512 		return (1);
513 	}
514 	kn->kn_flags &= ~EV_EOF;
515 	return (kn->kn_data > 0);
516 }
517 
518 void
519 filt_fifowdetach(struct knote *kn)
520 {
521 	struct socket *so = (struct socket *)kn->kn_hook;
522 
523 	SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
524 	if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
525 		so->so_snd.sb_flags &= ~SB_KNOTE;
526 }
527 
528 int
529 filt_fifowrite(struct knote *kn, long hint)
530 {
531 	struct socket *so = (struct socket *)kn->kn_hook;
532 
533 	kn->kn_data = sbspace(&so->so_snd);
534 	if (so->so_state & SS_CANTSENDMORE) {
535 		kn->kn_flags |= EV_EOF;
536 		return (1);
537 	}
538 	kn->kn_flags &= ~EV_EOF;
539 	return (kn->kn_data >= so->so_snd.sb_lowat);
540 }
541