xref: /freebsd/sys/fs/fifofs/fifo_vnops.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /*
2  * Copyright (c) 1990, 1993, 1995
3  *	The Regents of the University of California.  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	8.10 (Berkeley) 5/27/95
34  * $FreeBSD$
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/unistd.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/vnode.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/filio.h>
47 #include <sys/fcntl.h>
48 #include <sys/file.h>
49 #include <sys/event.h>
50 #include <sys/poll.h>
51 #include <sys/un.h>
52 #include <fs/fifofs/fifo.h>
53 
54 /*
55  * This structure is associated with the FIFO vnode and stores
56  * the state associated with the FIFO.
57  */
58 struct fifoinfo {
59 	struct socket	*fi_readsock;
60 	struct socket	*fi_writesock;
61 	long		fi_readers;
62 	long		fi_writers;
63 };
64 
65 static int	fifo_badop __P((void));
66 static int	fifo_print __P((struct vop_print_args *));
67 static int	fifo_lookup __P((struct vop_lookup_args *));
68 static int	fifo_open __P((struct vop_open_args *));
69 static int	fifo_close __P((struct vop_close_args *));
70 static int	fifo_read __P((struct vop_read_args *));
71 static int	fifo_write __P((struct vop_write_args *));
72 static int	fifo_ioctl __P((struct vop_ioctl_args *));
73 static int	fifo_poll __P((struct vop_poll_args *));
74 static int	fifo_kqfilter __P((struct vop_kqfilter_args *));
75 static int	fifo_pathconf __P((struct vop_pathconf_args *));
76 static int	fifo_advlock __P((struct vop_advlock_args *));
77 
78 static void	filt_fifordetach(struct knote *kn);
79 static int	filt_fiforead(struct knote *kn, long hint);
80 static void	filt_fifowdetach(struct knote *kn);
81 static int	filt_fifowrite(struct knote *kn, long hint);
82 
83 static struct filterops fiforead_filtops =
84 	{ 1, NULL, filt_fifordetach, filt_fiforead };
85 static struct filterops fifowrite_filtops =
86 	{ 1, NULL, filt_fifowdetach, filt_fifowrite };
87 
88 vop_t **fifo_vnodeop_p;
89 static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
90 	{ &vop_default_desc,		(vop_t *) vop_defaultop },
91 	{ &vop_access_desc,		(vop_t *) vop_ebadf },
92 	{ &vop_advlock_desc,		(vop_t *) fifo_advlock },
93 	{ &vop_close_desc,		(vop_t *) fifo_close },
94 	{ &vop_create_desc,		(vop_t *) fifo_badop },
95 	{ &vop_getattr_desc,		(vop_t *) vop_ebadf },
96 	{ &vop_getwritemount_desc, 	(vop_t *) vop_stdgetwritemount },
97 	{ &vop_ioctl_desc,		(vop_t *) fifo_ioctl },
98 	{ &vop_kqfilter_desc,		(vop_t *) fifo_kqfilter },
99 	{ &vop_lease_desc,		(vop_t *) vop_null },
100 	{ &vop_link_desc,		(vop_t *) fifo_badop },
101 	{ &vop_lookup_desc,		(vop_t *) fifo_lookup },
102 	{ &vop_mkdir_desc,		(vop_t *) fifo_badop },
103 	{ &vop_mknod_desc,		(vop_t *) fifo_badop },
104 	{ &vop_open_desc,		(vop_t *) fifo_open },
105 	{ &vop_pathconf_desc,		(vop_t *) fifo_pathconf },
106 	{ &vop_poll_desc,		(vop_t *) fifo_poll },
107 	{ &vop_print_desc,		(vop_t *) fifo_print },
108 	{ &vop_read_desc,		(vop_t *) fifo_read },
109 	{ &vop_readdir_desc,		(vop_t *) fifo_badop },
110 	{ &vop_readlink_desc,		(vop_t *) fifo_badop },
111 	{ &vop_reallocblks_desc,	(vop_t *) fifo_badop },
112 	{ &vop_reclaim_desc,		(vop_t *) vop_null },
113 	{ &vop_remove_desc,		(vop_t *) fifo_badop },
114 	{ &vop_rename_desc,		(vop_t *) fifo_badop },
115 	{ &vop_rmdir_desc,		(vop_t *) fifo_badop },
116 	{ &vop_setattr_desc,		(vop_t *) vop_ebadf },
117 	{ &vop_symlink_desc,		(vop_t *) fifo_badop },
118 	{ &vop_write_desc,		(vop_t *) fifo_write },
119 	{ NULL, NULL }
120 };
121 static struct vnodeopv_desc fifo_vnodeop_opv_desc =
122 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
123 
124 VNODEOP_SET(fifo_vnodeop_opv_desc);
125 
126 int
127 fifo_vnoperate(ap)
128 	struct vop_generic_args /* {
129 		struct vnodeop_desc *a_desc;
130 		<other random data follows, presumably>
131 	} */ *ap;
132 {
133 	return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
134 }
135 
136 /*
137  * Trivial lookup routine that always fails.
138  */
139 /* ARGSUSED */
140 static int
141 fifo_lookup(ap)
142 	struct vop_lookup_args /* {
143 		struct vnode * a_dvp;
144 		struct vnode ** a_vpp;
145 		struct componentname * a_cnp;
146 	} */ *ap;
147 {
148 
149 	*ap->a_vpp = NULL;
150 	return (ENOTDIR);
151 }
152 
153 /*
154  * Open called to set up a new instance of a fifo or
155  * to find an active instance of a fifo.
156  */
157 /* ARGSUSED */
158 static int
159 fifo_open(ap)
160 	struct vop_open_args /* {
161 		struct vnode *a_vp;
162 		int  a_mode;
163 		struct ucred *a_cred;
164 		struct proc *a_p;
165 	} */ *ap;
166 {
167 	struct vnode *vp = ap->a_vp;
168 	struct fifoinfo *fip;
169 	struct proc *p = ap->a_p;
170 	struct socket *rso, *wso;
171 	int error;
172 
173 	if ((fip = vp->v_fifoinfo) == NULL) {
174 		MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
175 		vp->v_fifoinfo = fip;
176 		error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_p);
177 		if (error) {
178 			free(fip, M_VNODE);
179 			vp->v_fifoinfo = NULL;
180 			return (error);
181 		}
182 		fip->fi_readsock = rso;
183 		error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
184 		if (error) {
185 			(void)soclose(rso);
186 			free(fip, M_VNODE);
187 			vp->v_fifoinfo = NULL;
188 			return (error);
189 		}
190 		fip->fi_writesock = wso;
191 		error = unp_connect2(wso, rso);
192 		if (error) {
193 			(void)soclose(wso);
194 			(void)soclose(rso);
195 			free(fip, M_VNODE);
196 			vp->v_fifoinfo = NULL;
197 			return (error);
198 		}
199 		fip->fi_readers = fip->fi_writers = 0;
200 		wso->so_snd.sb_lowat = PIPE_BUF;
201 		rso->so_state |= SS_CANTRCVMORE;
202 	}
203 	if (ap->a_mode & FREAD) {
204 		fip->fi_readers++;
205 		if (fip->fi_readers == 1) {
206 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
207 			if (fip->fi_writers > 0) {
208 				wakeup((caddr_t)&fip->fi_writers);
209 				sowwakeup(fip->fi_writesock);
210 			}
211 		}
212 	}
213 	if (ap->a_mode & FWRITE) {
214 		fip->fi_writers++;
215 		if (fip->fi_writers == 1) {
216 			fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
217 			if (fip->fi_readers > 0) {
218 				wakeup((caddr_t)&fip->fi_readers);
219 				sorwakeup(fip->fi_writesock);
220 			}
221 		}
222 	}
223 	if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
224 		while (fip->fi_writers == 0) {
225 			VOP_UNLOCK(vp, 0, p);
226 			error = tsleep((caddr_t)&fip->fi_readers,
227 			    PCATCH | PSOCK, "fifoor", 0);
228 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
229 			if (error)
230 				goto bad;
231 		}
232 	}
233 	if (ap->a_mode & FWRITE) {
234 		if (ap->a_mode & O_NONBLOCK) {
235 			if (fip->fi_readers == 0) {
236 				error = ENXIO;
237 				goto bad;
238 			}
239 		} else {
240 			while (fip->fi_readers == 0) {
241 				VOP_UNLOCK(vp, 0, p);
242 				error = tsleep((caddr_t)&fip->fi_writers,
243 				    PCATCH | PSOCK, "fifoow", 0);
244 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
245 				if (error)
246 					goto bad;
247 			}
248 		}
249 	}
250 	return (0);
251 bad:
252 	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
253 	return (error);
254 }
255 
256 /*
257  * Vnode op for read
258  */
259 /* ARGSUSED */
260 static int
261 fifo_read(ap)
262 	struct vop_read_args /* {
263 		struct vnode *a_vp;
264 		struct uio *a_uio;
265 		int  a_ioflag;
266 		struct ucred *a_cred;
267 	} */ *ap;
268 {
269 	struct uio *uio = ap->a_uio;
270 	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
271 	struct proc *p = uio->uio_procp;
272 	int error, startresid;
273 
274 #ifdef DIAGNOSTIC
275 	if (uio->uio_rw != UIO_READ)
276 		panic("fifo_read mode");
277 #endif
278 	if (uio->uio_resid == 0)
279 		return (0);
280 	if (ap->a_ioflag & IO_NDELAY)
281 		rso->so_state |= SS_NBIO;
282 	startresid = uio->uio_resid;
283 	VOP_UNLOCK(ap->a_vp, 0, p);
284 	error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
285 	    (struct mbuf **)0, (int *)0);
286 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
287 	if (ap->a_ioflag & IO_NDELAY)
288 		rso->so_state &= ~SS_NBIO;
289 	return (error);
290 }
291 
292 /*
293  * Vnode op for write
294  */
295 /* ARGSUSED */
296 static int
297 fifo_write(ap)
298 	struct vop_write_args /* {
299 		struct vnode *a_vp;
300 		struct uio *a_uio;
301 		int  a_ioflag;
302 		struct ucred *a_cred;
303 	} */ *ap;
304 {
305 	struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
306 	struct proc *p = ap->a_uio->uio_procp;
307 	int error;
308 
309 #ifdef DIAGNOSTIC
310 	if (ap->a_uio->uio_rw != UIO_WRITE)
311 		panic("fifo_write mode");
312 #endif
313 	if (ap->a_ioflag & IO_NDELAY)
314 		wso->so_state |= SS_NBIO;
315 	VOP_UNLOCK(ap->a_vp, 0, p);
316 	error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
317 		       (struct mbuf *)0, 0, p);
318 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
319 	if (ap->a_ioflag & IO_NDELAY)
320 		wso->so_state &= ~SS_NBIO;
321 	return (error);
322 }
323 
324 /*
325  * Device ioctl operation.
326  */
327 /* ARGSUSED */
328 static int
329 fifo_ioctl(ap)
330 	struct vop_ioctl_args /* {
331 		struct vnode *a_vp;
332 		int  a_command;
333 		caddr_t  a_data;
334 		int  a_fflag;
335 		struct ucred *a_cred;
336 		struct proc *a_p;
337 	} */ *ap;
338 {
339 	struct file filetmp;
340 	int error;
341 
342 	if (ap->a_command == FIONBIO)
343 		return (0);
344 	if (ap->a_fflag & FREAD) {
345 		filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
346 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
347 		if (error)
348 			return (error);
349 	}
350 	if (ap->a_fflag & FWRITE) {
351 		filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
352 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
353 		if (error)
354 			return (error);
355 	}
356 	return (0);
357 }
358 
359 /* ARGSUSED */
360 static int
361 fifo_kqfilter(ap)
362 	struct vop_kqfilter_args /* {
363 		struct vnode *a_vp;
364 		struct knote *a_kn;
365 	} */ *ap;
366 {
367 	struct fifoinfo *fi = ap->a_vp->v_fifoinfo;
368 	struct socket *so;
369 	struct sockbuf *sb;
370 
371 	switch (ap->a_kn->kn_filter) {
372 	case EVFILT_READ:
373 		ap->a_kn->kn_fop = &fiforead_filtops;
374 		so = fi->fi_readsock;
375 		sb = &so->so_rcv;
376 		break;
377 	case EVFILT_WRITE:
378 		ap->a_kn->kn_fop = &fifowrite_filtops;
379 		so = fi->fi_writesock;
380 		sb = &so->so_snd;
381 		break;
382 	default:
383 		return (1);
384 	}
385 
386 	ap->a_kn->kn_hook = (caddr_t)so;
387 
388 	SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
389 	sb->sb_flags |= SB_KNOTE;
390 
391 	return (0);
392 }
393 
394 static void
395 filt_fifordetach(struct knote *kn)
396 {
397 	struct socket *so = (struct socket *)kn->kn_hook;
398 
399 	SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
400 	if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
401 		so->so_rcv.sb_flags &= ~SB_KNOTE;
402 }
403 
404 static int
405 filt_fiforead(struct knote *kn, long hint)
406 {
407 	struct socket *so = (struct socket *)kn->kn_hook;
408 
409 	kn->kn_data = so->so_rcv.sb_cc;
410 	if (so->so_state & SS_CANTRCVMORE) {
411 		kn->kn_flags |= EV_EOF;
412 		return (1);
413 	}
414 	kn->kn_flags &= ~EV_EOF;
415 	return (kn->kn_data > 0);
416 }
417 
418 static void
419 filt_fifowdetach(struct knote *kn)
420 {
421 	struct socket *so = (struct socket *)kn->kn_hook;
422 
423 	SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
424 	if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
425 		so->so_snd.sb_flags &= ~SB_KNOTE;
426 }
427 
428 static int
429 filt_fifowrite(struct knote *kn, long hint)
430 {
431 	struct socket *so = (struct socket *)kn->kn_hook;
432 
433 	kn->kn_data = sbspace(&so->so_snd);
434 	if (so->so_state & SS_CANTSENDMORE) {
435 		kn->kn_flags |= EV_EOF;
436 		return (1);
437 	}
438 	kn->kn_flags &= ~EV_EOF;
439 	return (kn->kn_data >= so->so_snd.sb_lowat);
440 }
441 
442 /* ARGSUSED */
443 static int
444 fifo_poll(ap)
445 	struct vop_poll_args /* {
446 		struct vnode *a_vp;
447 		int  a_events;
448 		struct ucred *a_cred;
449 		struct proc *a_p;
450 	} */ *ap;
451 {
452 	struct file filetmp;
453 	int revents = 0;
454 
455 	if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
456 		filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
457 		if (filetmp.f_data)
458 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
459 			    ap->a_p);
460 	}
461 	if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
462 		filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
463 		if (filetmp.f_data)
464 			revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
465 			    ap->a_p);
466 	}
467 	return (revents);
468 }
469 
470 /*
471  * Device close routine
472  */
473 /* ARGSUSED */
474 static int
475 fifo_close(ap)
476 	struct vop_close_args /* {
477 		struct vnode *a_vp;
478 		int  a_fflag;
479 		struct ucred *a_cred;
480 		struct proc *a_p;
481 	} */ *ap;
482 {
483 	register struct vnode *vp = ap->a_vp;
484 	register struct fifoinfo *fip = vp->v_fifoinfo;
485 	int error1, error2;
486 
487 	if (ap->a_fflag & FREAD) {
488 		fip->fi_readers--;
489 		if (fip->fi_readers == 0)
490 			socantsendmore(fip->fi_writesock);
491 	}
492 	if (ap->a_fflag & FWRITE) {
493 		fip->fi_writers--;
494 		if (fip->fi_writers == 0)
495 			socantrcvmore(fip->fi_readsock);
496 	}
497 	if (vp->v_usecount > 1)
498 		return (0);
499 	error1 = soclose(fip->fi_readsock);
500 	error2 = soclose(fip->fi_writesock);
501 	FREE(fip, M_VNODE);
502 	vp->v_fifoinfo = NULL;
503 	if (error1)
504 		return (error1);
505 	return (error2);
506 }
507 
508 
509 /*
510  * Print out internal contents of a fifo vnode.
511  */
512 int
513 fifo_printinfo(vp)
514 	struct vnode *vp;
515 {
516 	register struct fifoinfo *fip = vp->v_fifoinfo;
517 
518 	printf(", fifo with %ld readers and %ld writers",
519 		fip->fi_readers, fip->fi_writers);
520 	return (0);
521 }
522 
523 /*
524  * Print out the contents of a fifo vnode.
525  */
526 static int
527 fifo_print(ap)
528 	struct vop_print_args /* {
529 		struct vnode *a_vp;
530 	} */ *ap;
531 {
532 
533 	printf("tag VT_NON");
534 	fifo_printinfo(ap->a_vp);
535 	printf("\n");
536 	return (0);
537 }
538 
539 /*
540  * Return POSIX pathconf information applicable to fifo's.
541  */
542 int
543 fifo_pathconf(ap)
544 	struct vop_pathconf_args /* {
545 		struct vnode *a_vp;
546 		int a_name;
547 		int *a_retval;
548 	} */ *ap;
549 {
550 
551 	switch (ap->a_name) {
552 	case _PC_LINK_MAX:
553 		*ap->a_retval = LINK_MAX;
554 		return (0);
555 	case _PC_PIPE_BUF:
556 		*ap->a_retval = PIPE_BUF;
557 		return (0);
558 	case _PC_CHOWN_RESTRICTED:
559 		*ap->a_retval = 1;
560 		return (0);
561 	default:
562 		return (EINVAL);
563 	}
564 	/* NOTREACHED */
565 }
566 
567 /*
568  * Fifo advisory byte-level locks.
569  */
570 /* ARGSUSED */
571 static int
572 fifo_advlock(ap)
573 	struct vop_advlock_args /* {
574 		struct vnode *a_vp;
575 		caddr_t  a_id;
576 		int  a_op;
577 		struct flock *a_fl;
578 		int  a_flags;
579 	} */ *ap;
580 {
581 
582 	return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
583 }
584 
585 /*
586  * Fifo bad operation
587  */
588 static int
589 fifo_badop()
590 {
591 
592 	panic("fifo_badop called");
593 	/* NOTREACHED */
594 }
595