xref: /openbsd/sys/miscfs/fifofs/fifo_vnops.c (revision 09467b48)
1 /*	$OpenBSD: fifo_vnops.c,v 1.77 2020/06/15 15:29:40 mpi 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/systm.h>
37 #include <sys/time.h>
38 #include <sys/namei.h>
39 #include <sys/vnode.h>
40 #include <sys/lock.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/stat.h>
45 #include <sys/ioctl.h>
46 #include <sys/fcntl.h>
47 #include <sys/file.h>
48 #include <sys/event.h>
49 #include <sys/errno.h>
50 #include <sys/malloc.h>
51 #include <sys/poll.h>
52 #include <sys/unistd.h>
53 
54 #include <miscfs/fifofs/fifo.h>
55 
56 /*
57  * This structure is associated with the FIFO vnode and stores
58  * the state associated with the FIFO.
59  */
60 struct fifoinfo {
61 	struct socket	*fi_readsock;
62 	struct socket	*fi_writesock;
63 	long		fi_readers;
64 	long		fi_writers;
65 };
66 
67 const struct vops fifo_vops = {
68 	.vop_lookup	= vop_generic_lookup,
69 	.vop_create	= fifo_badop,
70 	.vop_mknod	= fifo_badop,
71 	.vop_open	= fifo_open,
72 	.vop_close	= fifo_close,
73 	.vop_access	= fifo_ebadf,
74 	.vop_getattr	= fifo_ebadf,
75 	.vop_setattr	= fifo_ebadf,
76 	.vop_read	= fifo_read,
77 	.vop_write	= fifo_write,
78 	.vop_ioctl	= fifo_ioctl,
79 	.vop_poll	= fifo_poll,
80 	.vop_kqfilter	= fifo_kqfilter,
81 	.vop_revoke	= vop_generic_revoke,
82 	.vop_fsync	= nullop,
83 	.vop_remove	= fifo_badop,
84 	.vop_link	= fifo_badop,
85 	.vop_rename	= fifo_badop,
86 	.vop_mkdir	= fifo_badop,
87 	.vop_rmdir	= fifo_badop,
88 	.vop_symlink	= fifo_badop,
89 	.vop_readdir	= fifo_badop,
90 	.vop_readlink	= fifo_badop,
91 	.vop_abortop	= fifo_badop,
92 	.vop_inactive	= fifo_inactive,
93 	.vop_reclaim	= fifo_reclaim,
94 	.vop_lock	= vop_generic_lock,
95 	.vop_unlock	= vop_generic_unlock,
96 	.vop_bmap	= vop_generic_bmap,
97 	.vop_strategy	= fifo_badop,
98 	.vop_print	= fifo_print,
99 	.vop_islocked	= vop_generic_islocked,
100 	.vop_pathconf	= fifo_pathconf,
101 	.vop_advlock	= fifo_advlock,
102 	.vop_bwrite	= nullop
103 };
104 
105 void	filt_fifordetach(struct knote *kn);
106 int	filt_fiforead(struct knote *kn, long hint);
107 void	filt_fifowdetach(struct knote *kn);
108 int	filt_fifowrite(struct knote *kn, long hint);
109 
110 const struct filterops fiforead_filtops = {
111 	.f_flags	= FILTEROP_ISFD,
112 	.f_attach	= NULL,
113 	.f_detach	= filt_fifordetach,
114 	.f_event	= filt_fiforead,
115 };
116 
117 const struct filterops fifowrite_filtops = {
118 	.f_flags	= FILTEROP_ISFD,
119 	.f_attach	= NULL,
120 	.f_detach	= filt_fifowdetach,
121 	.f_event	= filt_fifowrite,
122 };
123 
124 /*
125  * Open called to set up a new instance of a fifo or
126  * to find an active instance of a fifo.
127  */
128 /* ARGSUSED */
129 int
130 fifo_open(void *v)
131 {
132 	struct vop_open_args *ap = v;
133 	struct vnode *vp = ap->a_vp;
134 	struct fifoinfo *fip;
135 	struct socket *rso, *wso;
136 	int s, error;
137 
138 	if ((fip = vp->v_fifoinfo) == NULL) {
139 		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
140 		vp->v_fifoinfo = fip;
141 		if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) {
142 			free(fip, M_VNODE, sizeof *fip);
143 			vp->v_fifoinfo = NULL;
144 			return (error);
145 		}
146 		fip->fi_readsock = rso;
147 		if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) {
148 			(void)soclose(rso, 0);
149 			free(fip, M_VNODE, sizeof *fip);
150 			vp->v_fifoinfo = NULL;
151 			return (error);
152 		}
153 		fip->fi_writesock = wso;
154 		if ((error = soconnect2(wso, rso)) != 0) {
155 			(void)soclose(wso, 0);
156 			(void)soclose(rso, 0);
157 			free(fip, M_VNODE, sizeof *fip);
158 			vp->v_fifoinfo = NULL;
159 			return (error);
160 		}
161 		fip->fi_readers = fip->fi_writers = 0;
162 		s = solock(wso);
163 		wso->so_state |= SS_CANTSENDMORE;
164 		wso->so_snd.sb_lowat = PIPE_BUF;
165 	} else {
166 		rso = fip->fi_readsock;
167 		wso = fip->fi_writesock;
168 		s = solock(wso);
169 	}
170 	if (ap->a_mode & FREAD) {
171 		fip->fi_readers++;
172 		if (fip->fi_readers == 1) {
173 			wso->so_state &= ~SS_CANTSENDMORE;
174 			if (fip->fi_writers > 0)
175 				wakeup(&fip->fi_writers);
176 		}
177 	}
178 	if (ap->a_mode & FWRITE) {
179 		fip->fi_writers++;
180 		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
181 			error = ENXIO;
182 			sounlock(wso, s);
183 			goto bad;
184 		}
185 		if (fip->fi_writers == 1) {
186 			rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED);
187 			if (fip->fi_readers > 0)
188 				wakeup(&fip->fi_readers);
189 		}
190 	}
191 	sounlock(wso, s);
192 	if ((ap->a_mode & O_NONBLOCK) == 0) {
193 		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
194 			VOP_UNLOCK(vp);
195 			error = tsleep_nsec(&fip->fi_readers,
196 			    PCATCH | PSOCK, "fifor", INFSLP);
197 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
198 			if (error)
199 				goto bad;
200 		}
201 		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
202 			VOP_UNLOCK(vp);
203 			error = tsleep_nsec(&fip->fi_writers,
204 			    PCATCH | PSOCK, "fifow", INFSLP);
205 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
206 			if (error)
207 				goto bad;
208 		}
209 	}
210 	return (0);
211 bad:
212 	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
213 	return (error);
214 }
215 
216 /*
217  * Vnode op for read
218  */
219 /* ARGSUSED */
220 int
221 fifo_read(void *v)
222 {
223 	struct vop_read_args *ap = v;
224 	struct uio *uio = ap->a_uio;
225 	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
226 	int error, flags = 0;
227 
228 #ifdef DIAGNOSTIC
229 	if (uio->uio_rw != UIO_READ)
230 		panic("fifo_read mode");
231 #endif
232 	if (uio->uio_resid == 0)
233 		return (0);
234 	if (ap->a_ioflag & IO_NDELAY)
235 		flags |= MSG_DONTWAIT;
236 	VOP_UNLOCK(ap->a_vp);
237 	error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0);
238 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
239 	if (ap->a_ioflag & IO_NDELAY) {
240 		if (error == EWOULDBLOCK &&
241 		    ap->a_vp->v_fifoinfo->fi_writers == 0)
242 			error = 0;
243 	}
244 	return (error);
245 }
246 
247 /*
248  * Vnode op for write
249  */
250 /* ARGSUSED */
251 int
252 fifo_write(void *v)
253 {
254 	struct vop_write_args *ap = v;
255 	struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
256 	int error, flags = 0;
257 
258 #ifdef DIAGNOSTIC
259 	if (ap->a_uio->uio_rw != UIO_WRITE)
260 		panic("fifo_write mode");
261 #endif
262 	if (ap->a_ioflag & IO_NDELAY)
263 		flags |= MSG_DONTWAIT;
264 	VOP_UNLOCK(ap->a_vp);
265 	error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags);
266 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
267 	return (error);
268 }
269 
270 /*
271  * Device ioctl operation.
272  */
273 /* ARGSUSED */
274 int
275 fifo_ioctl(void *v)
276 {
277 	struct vop_ioctl_args *ap = v;
278 	struct file filetmp;
279 	int error;
280 
281 	if (ap->a_command == FIONBIO)
282 		return (0);
283 	if (ap->a_fflag & FREAD) {
284 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
285 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
286 		if (error)
287 			return (error);
288 	}
289 	if (ap->a_fflag & FWRITE) {
290 		filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
291 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
292 		if (error)
293 			return (error);
294 	}
295 	return (0);
296 }
297 
298 /* ARGSUSED */
299 int
300 fifo_poll(void *v)
301 {
302 	struct vop_poll_args *ap = v;
303 	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
304 	struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
305 	int events = 0;
306 	int revents = 0;
307 	int s;
308 
309 	/*
310 	 * FIFOs don't support out-of-band or high priority data.
311 	 */
312 	s = solock(rso);
313 	if (ap->a_fflag & FREAD)
314 		events |= ap->a_events & (POLLIN | POLLRDNORM);
315 	if (ap->a_fflag & FWRITE)
316 		events |= ap->a_events & (POLLOUT | POLLWRNORM);
317 
318 	if (events & (POLLIN | POLLRDNORM)) {
319 		if (soreadable(rso))
320 			revents |= events & (POLLIN | POLLRDNORM);
321 	}
322 	/* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
323 	if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLL_NOHUP)) {
324 		revents |= POLLHUP;
325 	} else if (events & (POLLOUT | POLLWRNORM)) {
326 		if (sowriteable(wso))
327 			revents |= events & (POLLOUT | POLLWRNORM);
328 	}
329 	if (revents == 0) {
330 		/* We want to return POLLHUP even if no valid events set. */
331 		if (events == 0 && !(ap->a_events & POLL_NOHUP))
332 			events = POLLIN;
333 		if (events & (POLLIN | POLLRDNORM)) {
334 			selrecord(ap->a_p, &rso->so_rcv.sb_sel);
335 			rso->so_rcv.sb_flags |= SB_SEL;
336 		}
337 		if (events & (POLLOUT | POLLWRNORM)) {
338 			selrecord(ap->a_p, &wso->so_snd.sb_sel);
339 			wso->so_snd.sb_flags |= SB_SEL;
340 		}
341 	}
342 	sounlock(rso, s);
343 	return (revents);
344 }
345 
346 int
347 fifo_inactive(void *v)
348 {
349 	struct vop_inactive_args *ap = v;
350 
351 	VOP_UNLOCK(ap->a_vp);
352 	return (0);
353 }
354 
355 
356 /*
357  * Device close routine
358  */
359 /* ARGSUSED */
360 int
361 fifo_close(void *v)
362 {
363 	struct vop_close_args *ap = v;
364 	struct vnode *vp = ap->a_vp;
365 	struct fifoinfo *fip = vp->v_fifoinfo;
366 	int s, error1 = 0, error2 = 0;
367 
368 	if (fip == NULL)
369 		return (0);
370 
371 	if (ap->a_fflag & FREAD) {
372 		if (--fip->fi_readers == 0) {
373 			struct socket *wso = fip->fi_writesock;
374 
375 			s = solock(wso);
376 			socantsendmore(wso);
377 			sounlock(wso, s);
378 		}
379 	}
380 	if (ap->a_fflag & FWRITE) {
381 		if (--fip->fi_writers == 0) {
382 			struct socket *rso = fip->fi_readsock;
383 
384 			s = solock(rso);
385 			/* SS_ISDISCONNECTED will result in POLLHUP */
386 			rso->so_state |= SS_ISDISCONNECTED;
387 			socantrcvmore(rso);
388 			sounlock(rso, s);
389 		}
390 	}
391 	if (fip->fi_readers == 0 && fip->fi_writers == 0) {
392 		error1 = soclose(fip->fi_readsock, 0);
393 		error2 = soclose(fip->fi_writesock, 0);
394 		free(fip, M_VNODE, sizeof *fip);
395 		vp->v_fifoinfo = NULL;
396 	}
397 	return (error1 ? error1 : error2);
398 }
399 
400 int
401 fifo_reclaim(void *v)
402 {
403 	struct vop_reclaim_args *ap = v;
404 	struct vnode *vp = ap->a_vp;
405 	struct fifoinfo *fip = vp->v_fifoinfo;
406 
407 	if (fip == NULL)
408 		return (0);
409 
410 	soclose(fip->fi_readsock, 0);
411 	soclose(fip->fi_writesock, 0);
412 	free(fip, M_VNODE, sizeof *fip);
413 	vp->v_fifoinfo = NULL;
414 
415 	return (0);
416 }
417 
418 /*
419  * Print out the contents of a fifo vnode.
420  */
421 int
422 fifo_print(void *v)
423 {
424 	struct vop_print_args *ap = v;
425 
426 	printf("tag VT_NON");
427 	fifo_printinfo(ap->a_vp);
428 	printf("\n");
429 	return 0;
430 }
431 
432 /*
433  * Print out internal contents of a fifo vnode.
434  */
435 void
436 fifo_printinfo(struct vnode *vp)
437 {
438 	struct fifoinfo *fip = vp->v_fifoinfo;
439 
440 	printf(", fifo with %ld readers and %ld writers",
441 		fip->fi_readers, fip->fi_writers);
442 }
443 
444 /*
445  * Return POSIX pathconf information applicable to fifo's.
446  */
447 int
448 fifo_pathconf(void *v)
449 {
450 	struct vop_pathconf_args *ap = v;
451 	int error = 0;
452 
453 	switch (ap->a_name) {
454 	case _PC_LINK_MAX:
455 		*ap->a_retval = LINK_MAX;
456 		break;
457 	case _PC_CHOWN_RESTRICTED:
458 		*ap->a_retval = 1;
459 		break;
460 	case _PC_TIMESTAMP_RESOLUTION:
461 		*ap->a_retval = 1;
462 		break;
463 	default:
464 		error = EINVAL;
465 		break;
466 	}
467 
468 	return (error);
469 }
470 
471 /*
472  * Fifo failed operation
473  */
474 /*ARGSUSED*/
475 int
476 fifo_ebadf(void *v)
477 {
478 
479 	return (EBADF);
480 }
481 
482 /*
483  * Fifo advisory byte-level locks.
484  */
485 /* ARGSUSED */
486 int
487 fifo_advlock(void *v)
488 {
489 	return (EOPNOTSUPP);
490 }
491 
492 /*
493  * Fifo bad operation
494  */
495 /*ARGSUSED*/
496 int
497 fifo_badop(void *v)
498 {
499 
500 	panic("fifo_badop called");
501 	/* NOTREACHED */
502 	return(0);
503 }
504 
505 
506 int
507 fifo_kqfilter(void *v)
508 {
509 	struct vop_kqfilter_args *ap = v;
510 	struct fifoinfo *fip = ap->a_vp->v_fifoinfo;
511 	struct sockbuf *sb;
512 	struct socket *so;
513 
514 	switch (ap->a_kn->kn_filter) {
515 	case EVFILT_READ:
516 		if (!(ap->a_fflag & FREAD))
517 			return (EINVAL);
518 		ap->a_kn->kn_fop = &fiforead_filtops;
519 		so = fip->fi_readsock;
520 		sb = &so->so_rcv;
521 		break;
522 	case EVFILT_WRITE:
523 		if (!(ap->a_fflag & FWRITE))
524 			return (EINVAL);
525 		ap->a_kn->kn_fop = &fifowrite_filtops;
526 		so = fip->fi_writesock;
527 		sb = &so->so_snd;
528 		break;
529 	default:
530 		return (EINVAL);
531 	}
532 
533 	ap->a_kn->kn_hook = so;
534 
535 	klist_insert(&sb->sb_sel.si_note, ap->a_kn);
536 	sb->sb_flagsintr |= SB_KNOTE;
537 
538 	return (0);
539 }
540 
541 void
542 filt_fifordetach(struct knote *kn)
543 {
544 	struct socket *so = (struct socket *)kn->kn_hook;
545 
546 	klist_remove(&so->so_rcv.sb_sel.si_note, kn);
547 	if (klist_empty(&so->so_rcv.sb_sel.si_note))
548 		so->so_rcv.sb_flagsintr &= ~SB_KNOTE;
549 }
550 
551 int
552 filt_fiforead(struct knote *kn, long hint)
553 {
554 	struct socket *so = (struct socket *)kn->kn_hook;
555 	int s, rv;
556 
557 	if ((hint & NOTE_SUBMIT) == 0)
558 		s = solock(so);
559 	kn->kn_data = so->so_rcv.sb_cc;
560 	if (so->so_state & SS_CANTRCVMORE) {
561 		kn->kn_flags |= EV_EOF;
562 		if (kn->kn_flags & __EV_POLL) {
563 			if (so->so_state & SS_ISDISCONNECTED)
564 				kn->kn_flags |= __EV_HUP;
565 		}
566 		rv = 1;
567 	} else {
568 		kn->kn_flags &= ~EV_EOF;
569 		rv = (kn->kn_data > 0);
570 	}
571 	if ((hint & NOTE_SUBMIT) == 0)
572 		sounlock(so, s);
573 
574 	return (rv);
575 }
576 
577 void
578 filt_fifowdetach(struct knote *kn)
579 {
580 	struct socket *so = (struct socket *)kn->kn_hook;
581 
582 	klist_remove(&so->so_snd.sb_sel.si_note, kn);
583 	if (klist_empty(&so->so_snd.sb_sel.si_note))
584 		so->so_snd.sb_flagsintr &= ~SB_KNOTE;
585 }
586 
587 int
588 filt_fifowrite(struct knote *kn, long hint)
589 {
590 	struct socket *so = (struct socket *)kn->kn_hook;
591 	int s, rv;
592 
593 	if ((hint & NOTE_SUBMIT) == 0)
594 		s = solock(so);
595 	kn->kn_data = sbspace(so, &so->so_snd);
596 	if (so->so_state & SS_CANTSENDMORE) {
597 		kn->kn_flags |= EV_EOF;
598 		rv = 1;
599 	} else {
600 		kn->kn_flags &= ~EV_EOF;
601 		rv = (kn->kn_data >= so->so_snd.sb_lowat);
602 	}
603 	if ((hint & NOTE_SUBMIT) == 0)
604 		sounlock(so, s);
605 
606 	return (rv);
607 }
608