xref: /openbsd/sys/miscfs/fifofs/fifo_vnops.c (revision 17df1aa7)
1 /*	$OpenBSD: fifo_vnops.c,v 1.31 2009/08/13 15:00:14 jasper 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 int (**fifo_vnodeop_p)(void *);
65 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
66 	{ &vop_default_desc, eopnotsupp },
67 	{ &vop_lookup_desc, vop_generic_lookup },
68 	{ &vop_create_desc, fifo_badop },
69 	{ &vop_mknod_desc, fifo_badop },
70 	{ &vop_open_desc, fifo_open },
71 	{ &vop_close_desc, fifo_close },
72 	{ &vop_access_desc, fifo_ebadf },
73 	{ &vop_getattr_desc, fifo_ebadf },
74 	{ &vop_setattr_desc, fifo_ebadf },
75 	{ &vop_read_desc, fifo_read },
76 	{ &vop_write_desc, fifo_write },
77 	{ &vop_ioctl_desc, fifo_ioctl },
78 	{ &vop_poll_desc, fifo_poll },
79 	{ &vop_kqfilter_desc, fifo_kqfilter },
80 	{ &vop_revoke_desc, vop_generic_revoke },
81 	{ &vop_fsync_desc, nullop },
82 	{ &vop_remove_desc, fifo_badop },
83 	{ &vop_link_desc, fifo_badop },
84 	{ &vop_rename_desc, fifo_badop },
85 	{ &vop_mkdir_desc, fifo_badop },
86 	{ &vop_rmdir_desc, fifo_badop },
87 	{ &vop_symlink_desc, fifo_badop },
88 	{ &vop_readdir_desc, fifo_badop },
89 	{ &vop_readlink_desc, fifo_badop },
90 	{ &vop_abortop_desc, fifo_badop },
91 	{ &vop_inactive_desc, fifo_inactive },
92 	{ &vop_reclaim_desc, fifo_reclaim },
93 	{ &vop_lock_desc, vop_generic_lock },
94 	{ &vop_unlock_desc, vop_generic_unlock },
95 	{ &vop_bmap_desc, vop_generic_bmap },
96 	{ &vop_strategy_desc, fifo_badop },
97 	{ &vop_print_desc, fifo_print },
98 	{ &vop_islocked_desc, vop_generic_islocked },
99 	{ &vop_pathconf_desc, fifo_pathconf },
100 	{ &vop_advlock_desc, fifo_advlock },
101 	{ &vop_bwrite_desc, nullop },
102 	{ NULL, NULL }
103 };
104 
105 struct vnodeopv_desc fifo_vnodeop_opv_desc =
106 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
107 
108 int
109 fifo_vnoperate(void *v)
110 {
111 	struct vop_generic_args *ap = v;
112 
113 	return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
114 }
115 
116 void	filt_fifordetach(struct knote *kn);
117 int	filt_fiforead(struct knote *kn, long hint);
118 void	filt_fifowdetach(struct knote *kn);
119 int	filt_fifowrite(struct knote *kn, long hint);
120 
121 struct filterops fiforead_filtops =
122 	{ 1, NULL, filt_fifordetach, filt_fiforead };
123 struct filterops fifowrite_filtops =
124 	{ 1, NULL, filt_fifowdetach, filt_fifowrite };
125 
126 /*
127  * Open called to set up a new instance of a fifo or
128  * to find an active instance of a fifo.
129  */
130 /* ARGSUSED */
131 int
132 fifo_open(void *v)
133 {
134 	struct vop_open_args *ap = v;
135 	struct vnode *vp = ap->a_vp;
136 	struct fifoinfo *fip;
137 	struct proc *p = ap->a_p;
138 	struct socket *rso, *wso;
139 	int error;
140 
141 	if ((fip = vp->v_fifoinfo) == NULL) {
142 		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
143 		vp->v_fifoinfo = fip;
144 		if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
145 			free(fip, M_VNODE);
146 			vp->v_fifoinfo = NULL;
147 			return (error);
148 		}
149 		fip->fi_readsock = rso;
150 		if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
151 			(void)soclose(rso);
152 			free(fip, M_VNODE);
153 			vp->v_fifoinfo = NULL;
154 			return (error);
155 		}
156 		fip->fi_writesock = wso;
157 		if ((error = unp_connect2(wso, rso)) != 0) {
158 			(void)soclose(wso);
159 			(void)soclose(rso);
160 			free(fip, M_VNODE);
161 			vp->v_fifoinfo = NULL;
162 			return (error);
163 		}
164 		fip->fi_readers = fip->fi_writers = 0;
165 		wso->so_snd.sb_lowat = PIPE_BUF;
166 		rso->so_state |= SS_CANTRCVMORE;
167 	}
168 	if (ap->a_mode & FREAD) {
169 		fip->fi_readers++;
170 		if (fip->fi_readers == 1) {
171 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
172 			if (fip->fi_writers > 0)
173 				wakeup(&fip->fi_writers);
174 		}
175 	}
176 	if (ap->a_mode & FWRITE) {
177 		fip->fi_writers++;
178 		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
179 			error = ENXIO;
180 			goto bad;
181 		}
182 		if (fip->fi_writers == 1) {
183 			fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
184 			if (fip->fi_readers > 0)
185 				wakeup(&fip->fi_readers);
186 		}
187 	}
188 	if ((ap->a_mode & O_NONBLOCK) == 0) {
189 		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
190 			VOP_UNLOCK(vp, 0, p);
191 			error = tsleep(&fip->fi_readers,
192 			    PCATCH | PSOCK, "fifor", 0);
193 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
194 			if (error)
195 				goto bad;
196 		}
197 		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
198 			VOP_UNLOCK(vp, 0, p);
199 			error = tsleep(&fip->fi_writers,
200 			    PCATCH | PSOCK, "fifow", 0);
201 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
202 			if (error)
203 				goto bad;
204 		}
205 	}
206 	return (0);
207 bad:
208 	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
209 	return (error);
210 }
211 
212 /*
213  * Vnode op for read
214  */
215 /* ARGSUSED */
216 int
217 fifo_read(void *v)
218 {
219 	struct vop_read_args *ap = v;
220 	struct uio *uio = ap->a_uio;
221 	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
222 	struct proc *p = uio->uio_procp;
223 	int error;
224 
225 #ifdef DIAGNOSTIC
226 	if (uio->uio_rw != UIO_READ)
227 		panic("fifo_read mode");
228 #endif
229 	if (uio->uio_resid == 0)
230 		return (0);
231 	if (ap->a_ioflag & IO_NDELAY)
232 		rso->so_state |= SS_NBIO;
233 	VOP_UNLOCK(ap->a_vp, 0, p);
234 	error = soreceive(rso, NULL, uio, NULL, NULL, NULL, 0);
235 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
236 	if (ap->a_ioflag & IO_NDELAY) {
237 		rso->so_state &= ~SS_NBIO;
238 		if (error == EWOULDBLOCK &&
239 		    ap->a_vp->v_fifoinfo->fi_writers == 0)
240 			error = 0;
241 	}
242 	return (error);
243 }
244 
245 /*
246  * Vnode op for write
247  */
248 /* ARGSUSED */
249 int
250 fifo_write(void *v)
251 {
252 	struct vop_write_args *ap = v;
253 	struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
254 	struct proc *p = ap->a_uio->uio_procp;
255 	int error;
256 
257 #ifdef DIAGNOSTIC
258 	if (ap->a_uio->uio_rw != UIO_WRITE)
259 		panic("fifo_write mode");
260 #endif
261 	if (ap->a_ioflag & IO_NDELAY)
262 		wso->so_state |= SS_NBIO;
263 	VOP_UNLOCK(ap->a_vp, 0, p);
264 	error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
265 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
266 	if (ap->a_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(void *v)
277 {
278 	struct vop_ioctl_args *ap = v;
279 	struct file filetmp;
280 	int error;
281 
282 	if (ap->a_command == FIONBIO)
283 		return (0);
284 	if (ap->a_fflag & FREAD) {
285 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
286 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
287 		if (error)
288 			return (error);
289 	}
290 	if (ap->a_fflag & FWRITE) {
291 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
292 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
293 		if (error)
294 			return (error);
295 	}
296 	return (0);
297 }
298 
299 /* ARGSUSED */
300 int
301 fifo_poll(void *v)
302 {
303 	struct vop_poll_args *ap = v;
304 	struct file filetmp;
305 	short ostate;
306 	int revents = 0;
307 
308 	if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
309 		/*
310 		 * Socket and FIFO poll(2) semantics differ wrt EOF on read.
311 		 * Unlike a normal socket, FIFOs don't care whether or not
312 		 * SS_CANTRCVMORE is set.  To get the correct semantics we
313 		 * must clear SS_CANTRCVMORE from so_state temporarily.
314 		 */
315 		ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
316 		if (ap->a_events & (POLLIN | POLLRDNORM))
317 			ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
318 			    ~SS_CANTRCVMORE;
319 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
320 		if (filetmp.f_data)
321 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
322 		ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
323 	}
324 	if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
325 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
326 		if (filetmp.f_data)
327 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
328 	}
329 	return (revents);
330 }
331 
332 int
333 fifo_inactive(void *v)
334 {
335 	struct vop_inactive_args *ap = v;
336 
337 	VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
338 	return (0);
339 }
340 
341 
342 /*
343  * Device close routine
344  */
345 /* ARGSUSED */
346 int
347 fifo_close(void *v)
348 {
349 	struct vop_close_args *ap = v;
350 	struct vnode *vp = ap->a_vp;
351 	struct fifoinfo *fip = vp->v_fifoinfo;
352 	int error1 = 0, error2 = 0;
353 
354 	if (fip == NULL)
355 		return (0);
356 
357 	if (ap->a_fflag & FREAD) {
358 		if (--fip->fi_readers == 0)
359 			socantsendmore(fip->fi_writesock);
360 	}
361 	if (ap->a_fflag & FWRITE) {
362 		if (--fip->fi_writers == 0)
363 			socantrcvmore(fip->fi_readsock);
364 	}
365 	if (fip->fi_readers == 0 && fip->fi_writers == 0) {
366 		error1 = soclose(fip->fi_readsock);
367 		error2 = soclose(fip->fi_writesock);
368 		free(fip, M_VNODE);
369 		vp->v_fifoinfo = NULL;
370 	}
371 	return (error1 ? error1 : error2);
372 }
373 
374 int
375 fifo_reclaim(void *v)
376 {
377 	struct vop_reclaim_args *ap = v;
378 	struct vnode *vp = ap->a_vp;
379 	struct fifoinfo *fip = vp->v_fifoinfo;
380 
381 	if (fip == NULL)
382 		return (0);
383 
384 	soclose(fip->fi_readsock);
385 	soclose(fip->fi_writesock);
386 	free(fip, M_VNODE);
387 	vp->v_fifoinfo = NULL;
388 
389 	return (0);
390 }
391 
392 /*
393  * Print out the contents of a fifo vnode.
394  */
395 int
396 fifo_print(void *v)
397 {
398 	struct vop_print_args *ap = v;
399 
400 	printf("tag VT_NON");
401 	fifo_printinfo(ap->a_vp);
402 	printf("\n");
403 	return 0;
404 }
405 
406 /*
407  * Print out internal contents of a fifo vnode.
408  */
409 void
410 fifo_printinfo(struct vnode *vp)
411 {
412 	struct fifoinfo *fip = vp->v_fifoinfo;
413 
414 	printf(", fifo with %ld readers and %ld writers",
415 		fip->fi_readers, fip->fi_writers);
416 }
417 
418 /*
419  * Return POSIX pathconf information applicable to fifo's.
420  */
421 int
422 fifo_pathconf(void *v)
423 {
424 	struct vop_pathconf_args *ap = v;
425 
426 	switch (ap->a_name) {
427 	case _PC_LINK_MAX:
428 		*ap->a_retval = LINK_MAX;
429 		return (0);
430 	case _PC_PIPE_BUF:
431 		*ap->a_retval = PIPE_BUF;
432 		return (0);
433 	case _PC_CHOWN_RESTRICTED:
434 		*ap->a_retval = 1;
435 		return (0);
436 	default:
437 		return (EINVAL);
438 	}
439 	/* NOTREACHED */
440 }
441 
442 /*
443  * Fifo failed operation
444  */
445 /*ARGSUSED*/
446 int
447 fifo_ebadf(void *v)
448 {
449 
450 	return (EBADF);
451 }
452 
453 /*
454  * Fifo advisory byte-level locks.
455  */
456 /* ARGSUSED */
457 int
458 fifo_advlock(void *v)
459 {
460 	return (EOPNOTSUPP);
461 }
462 
463 /*
464  * Fifo bad operation
465  */
466 /*ARGSUSED*/
467 int
468 fifo_badop(void *v)
469 {
470 
471 	panic("fifo_badop called");
472 	/* NOTREACHED */
473 	return(0);
474 }
475 
476 
477 int
478 fifo_kqfilter(void *v)
479 {
480 	struct vop_kqfilter_args *ap = v;
481 	struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
482 	struct sockbuf *sb;
483 
484 	switch (ap->a_kn->kn_filter) {
485 	case EVFILT_READ:
486 		ap->a_kn->kn_fop = &fiforead_filtops;
487 		sb = &so->so_rcv;
488 		break;
489 	case EVFILT_WRITE:
490 		ap->a_kn->kn_fop = &fifowrite_filtops;
491 		sb = &so->so_snd;
492 		break;
493 	default:
494 		return (1);
495 	}
496 
497 	ap->a_kn->kn_hook = so;
498 
499 	SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
500 	sb->sb_flags |= SB_KNOTE;
501 
502 	return (0);
503 }
504 
505 void
506 filt_fifordetach(struct knote *kn)
507 {
508 	struct socket *so = (struct socket *)kn->kn_hook;
509 
510 	SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
511 	if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
512 		so->so_rcv.sb_flags &= ~SB_KNOTE;
513 }
514 
515 int
516 filt_fiforead(struct knote *kn, long hint)
517 {
518 	struct socket *so = (struct socket *)kn->kn_hook;
519 
520 	kn->kn_data = so->so_rcv.sb_cc;
521 	if (so->so_state & SS_CANTRCVMORE) {
522 		kn->kn_flags |= EV_EOF;
523 		return (1);
524 	}
525 	kn->kn_flags &= ~EV_EOF;
526 	return (kn->kn_data > 0);
527 }
528 
529 void
530 filt_fifowdetach(struct knote *kn)
531 {
532 	struct socket *so = (struct socket *)kn->kn_hook;
533 
534 	SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
535 	if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
536 		so->so_snd.sb_flags &= ~SB_KNOTE;
537 }
538 
539 int
540 filt_fifowrite(struct knote *kn, long hint)
541 {
542 	struct socket *so = (struct socket *)kn->kn_hook;
543 
544 	kn->kn_data = sbspace(&so->so_snd);
545 	if (so->so_state & SS_CANTSENDMORE) {
546 		kn->kn_flags |= EV_EOF;
547 		return (1);
548 	}
549 	kn->kn_flags &= ~EV_EOF;
550 	return (kn->kn_data >= so->so_snd.sb_lowat);
551 }
552