xref: /dragonfly/sys/vfs/fifofs/fifo_vnops.c (revision 3170ffd7)
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  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 /*
30  * Filesystem FIFO type ops.  All entry points are MPSAFE.  We primarily
31  * use v_token to interlock operations.
32  */
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/unistd.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/malloc.h>
39 #include <sys/thread2.h>
40 #include <sys/vnode.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/filio.h>
44 #include <sys/fcntl.h>
45 #include <sys/file.h>
46 #include <sys/event.h>
47 #include <sys/un.h>
48 
49 #include <sys/thread2.h>
50 #include <sys/socketvar2.h>
51 
52 #include "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 (void);
66 static int	fifo_print (struct vop_print_args *);
67 static int	fifo_lookup (struct vop_old_lookup_args *);
68 static int	fifo_open (struct vop_open_args *);
69 static int	fifo_close (struct vop_close_args *);
70 static int	fifo_read (struct vop_read_args *);
71 static int	fifo_write (struct vop_write_args *);
72 static int	fifo_ioctl (struct vop_ioctl_args *);
73 static int	fifo_kqfilter (struct vop_kqfilter_args *);
74 static int	fifo_inactive (struct  vop_inactive_args *);
75 static int	fifo_bmap (struct vop_bmap_args *);
76 static int	fifo_pathconf (struct vop_pathconf_args *);
77 static int	fifo_advlock (struct vop_advlock_args *);
78 
79 static void	filt_fifordetach(struct knote *kn);
80 static int	filt_fiforead(struct knote *kn, long hint);
81 static void	filt_fifowdetach(struct knote *kn);
82 static int	filt_fifowrite(struct knote *kn, long hint);
83 
84 static struct filterops fiforead_filtops =
85 	{ FILTEROP_ISFD, NULL, filt_fifordetach, filt_fiforead };
86 static struct filterops fifowrite_filtops =
87 	{ FILTEROP_ISFD, NULL, filt_fifowdetach, filt_fifowrite };
88 
89 struct vop_ops fifo_vnode_vops = {
90 	.vop_default =		vop_defaultop,
91 	.vop_access =		(void *)vop_ebadf,
92 	.vop_advlock =		fifo_advlock,
93 	.vop_bmap =		fifo_bmap,
94 	.vop_close =		fifo_close,
95 	.vop_old_create =	(void *)fifo_badop,
96 	.vop_getattr =		(void *)vop_ebadf,
97 	.vop_inactive =		fifo_inactive,
98 	.vop_ioctl =		fifo_ioctl,
99 	.vop_kqfilter =		fifo_kqfilter,
100 	.vop_old_link =		(void *)fifo_badop,
101 	.vop_old_lookup =	fifo_lookup,
102 	.vop_old_mkdir =	(void *)fifo_badop,
103 	.vop_old_mknod =	(void *)fifo_badop,
104 	.vop_open =		fifo_open,
105 	.vop_pathconf =		fifo_pathconf,
106 	.vop_print =		fifo_print,
107 	.vop_read =		fifo_read,
108 	.vop_readdir =		(void *)fifo_badop,
109 	.vop_readlink =		(void *)fifo_badop,
110 	.vop_reallocblks =	(void *)fifo_badop,
111 	.vop_reclaim =		(void *)vop_null,
112 	.vop_old_remove =	(void *)fifo_badop,
113 	.vop_old_rename =	(void *)fifo_badop,
114 	.vop_old_rmdir =	(void *)fifo_badop,
115 	.vop_setattr =		(void *)vop_ebadf,
116 	.vop_old_symlink =	(void *)fifo_badop,
117 	.vop_write =		fifo_write
118 };
119 
120 VNODEOP_SET(fifo_vnode_vops);
121 
122 static MALLOC_DEFINE(M_FIFOINFO, "Fifo info", "Fifo info entries");
123 
124 /*
125  * fifo_vnoperate()
126  */
127 int
128 fifo_vnoperate(struct vop_generic_args *ap)
129 {
130 	return (VOCALL(&fifo_vnode_vops, ap));
131 }
132 
133 /*
134  * Trivial lookup routine that always fails.
135  *
136  * fifo_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
137  *	       struct componentname *a_cnp)
138  */
139 /* ARGSUSED */
140 static int
141 fifo_lookup(struct vop_old_lookup_args *ap)
142 {
143 	*ap->a_vpp = NULL;
144 	return (ENOTDIR);
145 }
146 
147 /*
148  * Open called to set up a new instance of a fifo or
149  * to find an active instance of a fifo.
150  *
151  * fifo_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
152  *	     struct file *a_fp)
153  */
154 /* ARGSUSED */
155 static int
156 fifo_open(struct vop_open_args *ap)
157 {
158 	struct thread *td = curthread;
159 	struct vnode *vp = ap->a_vp;
160 	struct fifoinfo *fip;
161 	struct socket *rso, *wso;
162 	int error;
163 
164 	lwkt_gettoken(&vp->v_token);
165 	if ((fip = vp->v_fifoinfo) == NULL) {
166 		fip = kmalloc(sizeof(*fip), M_FIFOINFO, M_WAITOK);
167 		vp->v_fifoinfo = fip;
168 		error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, td);
169 		if (error) {
170 			kfree(fip, M_FIFOINFO);
171 			vp->v_fifoinfo = NULL;
172 			goto done;
173 		}
174 		fip->fi_readsock = rso;
175 		error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, td);
176 		if (error) {
177 			soclose(rso, FNONBLOCK);
178 			kfree(fip, M_FIFOINFO);
179 			vp->v_fifoinfo = NULL;
180 			goto done;
181 		}
182 		fip->fi_writesock = wso;
183 		error = unp_connect2(wso, rso);
184 		if (error) {
185 			soclose(wso, FNONBLOCK);
186 			soclose(rso, FNONBLOCK);
187 			kfree(fip, M_FIFOINFO);
188 			vp->v_fifoinfo = NULL;
189 			goto done;
190 		}
191 		fip->fi_readers = fip->fi_writers = 0;
192 		wso->so_snd.ssb_lowat = PIPE_BUF;
193 		sosetstate(rso, SS_CANTRCVMORE);
194 	}
195 	if (ap->a_mode & FREAD) {
196 		fip->fi_readers++;
197 		if (fip->fi_readers == 1) {
198 			soisreconnected(fip->fi_writesock);
199 			if (fip->fi_writers > 0) {
200 				wakeup((caddr_t)&fip->fi_writers);
201 				sowwakeup(fip->fi_writesock);
202 			}
203 		}
204 	}
205 	if (ap->a_mode & FWRITE) {
206 		fip->fi_writers++;
207 		if (fip->fi_writers == 1) {
208 			soisreconnected(fip->fi_readsock);
209 			if (fip->fi_readers > 0) {
210 				wakeup((caddr_t)&fip->fi_readers);
211 				sorwakeup(fip->fi_writesock);
212 			}
213 		}
214 	}
215 	if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
216 		if (fip->fi_writers == 0) {
217 			vn_unlock(vp);
218 			error = tsleep((caddr_t)&fip->fi_readers,
219 			    PCATCH, "fifoor", 0);
220 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
221 			if (error)
222 				goto bad;
223 			/*
224 			 * We must have got woken up because we had a writer.
225 			 * That (and not still having one) is the condition
226 			 * that we must wait for.
227 			 */
228 		}
229 	}
230 	if (ap->a_mode & FWRITE) {
231 		if (ap->a_mode & O_NONBLOCK) {
232 			if (fip->fi_readers == 0) {
233 				error = ENXIO;
234 				goto bad;
235 			}
236 		} else {
237 			if (fip->fi_readers == 0) {
238 				vn_unlock(vp);
239 				error = tsleep((caddr_t)&fip->fi_writers,
240 				    PCATCH, "fifoow", 0);
241 				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
242 				if (error)
243 					goto bad;
244 				/*
245 				 * We must have got woken up because we had
246 				 * a reader.  That (and not still having one)
247 				 * is the condition that we must wait for.
248 				 */
249 			}
250 		}
251 	}
252 	vsetflags(vp, VNOTSEEKABLE);
253 	error = vop_stdopen(ap);
254 	lwkt_reltoken(&vp->v_token);
255 	return (error);
256 bad:
257 	vop_stdopen(ap);	/* bump opencount/writecount as appropriate */
258 	VOP_CLOSE(vp, ap->a_mode);
259 done:
260 	lwkt_reltoken(&vp->v_token);
261 	return (error);
262 }
263 
264 /*
265  * Vnode op for read
266  *
267  * fifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
268  *	     struct ucred *a_cred)
269  */
270 /* ARGSUSED */
271 static int
272 fifo_read(struct vop_read_args *ap)
273 {
274 	struct uio *uio = ap->a_uio;
275 	struct vnode *vp = ap->a_vp;
276 	struct socket *rso = vp->v_fifoinfo->fi_readsock;
277 	int error;
278 	int flags;
279 
280 #ifdef DIAGNOSTIC
281 	if (uio->uio_rw != UIO_READ)
282 		panic("fifo_read mode");
283 #endif
284 	if (uio->uio_resid == 0)
285 		return (0);
286 	if (ap->a_ioflag & IO_NDELAY)
287 		flags = MSG_FNONBLOCKING;
288 	else
289 		flags = 0;
290 	vn_unlock(vp);
291 	lwkt_gettoken(&vp->v_token);
292 	error = soreceive(rso, NULL, uio, NULL, NULL, &flags);
293 	lwkt_reltoken(&vp->v_token);
294 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
295 	return (error);
296 }
297 
298 /*
299  * Vnode op for write
300  *
301  * fifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
302  *	      struct ucred *a_cred)
303  */
304 /* ARGSUSED */
305 static int
306 fifo_write(struct vop_write_args *ap)
307 {
308 	struct thread *td = ap->a_uio->uio_td;
309 	struct vnode *vp = ap->a_vp;
310 	struct socket *wso = vp->v_fifoinfo->fi_writesock;
311 	int error;
312 	int flags;
313 
314 #ifdef DIAGNOSTIC
315 	if (ap->a_uio->uio_rw != UIO_WRITE)
316 		panic("fifo_write mode");
317 #endif
318 	if (ap->a_ioflag & IO_NDELAY)
319 		flags = MSG_FNONBLOCKING;
320 	else
321 		flags = 0;
322 	vn_unlock(vp);
323 	lwkt_gettoken(&vp->v_token);
324 	error = sosend(wso, NULL, ap->a_uio, 0, NULL, flags, td);
325 	lwkt_reltoken(&vp->v_token);
326 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
327 	return (error);
328 }
329 
330 /*
331  * Device ioctl operation.
332  *
333  * fifo_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, int a_fflag,
334  *	      struct ucred *a_cred, struct sysmsg *a_sysmsg)
335  */
336 /* ARGSUSED */
337 static int
338 fifo_ioctl(struct vop_ioctl_args *ap)
339 {
340 	struct file filetmp;	/* Local */
341 	struct vnode *vp = ap->a_vp;
342 	int error;
343 
344 	if (ap->a_fflag & FREAD) {
345 		filetmp.f_data = vp->v_fifoinfo->fi_readsock;
346 		lwkt_gettoken(&vp->v_token);
347 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data,
348 				  ap->a_cred, ap->a_sysmsg);
349 		lwkt_reltoken(&vp->v_token);
350 		if (error)
351 			return (error);
352 	}
353 	if (ap->a_fflag & FWRITE) {
354 		filetmp.f_data = vp->v_fifoinfo->fi_writesock;
355 		lwkt_gettoken(&vp->v_token);
356 		error = soo_ioctl(&filetmp, ap->a_command, ap->a_data,
357 				  ap->a_cred, ap->a_sysmsg);
358 		lwkt_reltoken(&vp->v_token);
359 		if (error)
360 			return (error);
361 	}
362 	return (0);
363 }
364 
365 /*
366  * fifo_kqfilter(struct vnode *a_vp, struct knote *a_kn)
367  */
368 /* ARGSUSED */
369 static int
370 fifo_kqfilter(struct vop_kqfilter_args *ap)
371 {
372 	struct vnode *vp = ap->a_vp;
373 	struct fifoinfo *fi = vp->v_fifoinfo;
374 	struct socket *so;
375 	struct signalsockbuf *ssb;
376 
377 	lwkt_gettoken(&vp->v_token);
378 
379 	switch (ap->a_kn->kn_filter) {
380 	case EVFILT_READ:
381 		ap->a_kn->kn_fop = &fiforead_filtops;
382 		so = fi->fi_readsock;
383 		ssb = &so->so_rcv;
384 		break;
385 	case EVFILT_WRITE:
386 		ap->a_kn->kn_fop = &fifowrite_filtops;
387 		so = fi->fi_writesock;
388 		ssb = &so->so_snd;
389 		break;
390 	default:
391 		lwkt_reltoken(&vp->v_token);
392 		return (EOPNOTSUPP);
393 	}
394 
395 	ap->a_kn->kn_hook = (caddr_t)vp;
396 	ssb_insert_knote(ssb, ap->a_kn);
397 
398 	lwkt_reltoken(&vp->v_token);
399 	return (0);
400 }
401 
402 static void
403 filt_fifordetach(struct knote *kn)
404 {
405 	struct vnode *vp = (void *)kn->kn_hook;
406 	struct socket *so = vp->v_fifoinfo->fi_readsock;
407 
408 	lwkt_gettoken(&vp->v_token);
409 	ssb_remove_knote(&so->so_rcv, kn);
410 	lwkt_reltoken(&vp->v_token);
411 }
412 
413 static int
414 filt_fiforead(struct knote *kn, long hint)
415 {
416 	struct vnode *vp = (void *)kn->kn_hook;
417 	struct socket *so = vp->v_fifoinfo->fi_readsock;
418 
419 	lwkt_gettoken(&vp->v_token);
420 	kn->kn_data = so->so_rcv.ssb_cc;
421 	if ((kn->kn_sfflags & NOTE_OLDAPI) == 0 &&
422 	    so->so_state & SS_ISDISCONNECTED) {
423 		if (kn->kn_data == 0)
424 			kn->kn_flags |= EV_NODATA;
425 		kn->kn_flags |= EV_EOF;
426 		lwkt_reltoken(&vp->v_token);
427 		return (1);
428 	}
429 	kn->kn_flags &= ~(EV_EOF | EV_NODATA);
430 	lwkt_reltoken(&vp->v_token);
431 	return (kn->kn_data > 0);
432 }
433 
434 static void
435 filt_fifowdetach(struct knote *kn)
436 {
437 	struct vnode *vp = (void *)kn->kn_hook;
438 	struct socket *so = vp->v_fifoinfo->fi_writesock;
439 
440 	lwkt_gettoken(&vp->v_token);
441 	ssb_remove_knote(&so->so_snd, kn);
442 	lwkt_reltoken(&vp->v_token);
443 }
444 
445 static int
446 filt_fifowrite(struct knote *kn, long hint)
447 {
448 	struct vnode *vp = (void *)kn->kn_hook;
449 	struct socket *so = vp->v_fifoinfo->fi_writesock;
450 
451 	lwkt_gettoken(&vp->v_token);
452 	kn->kn_data = ssb_space(&so->so_snd);
453 	if (so->so_state & SS_ISDISCONNECTED) {
454 		kn->kn_flags |= (EV_EOF | EV_NODATA);
455 		lwkt_reltoken(&vp->v_token);
456 		return (1);
457 	}
458 	kn->kn_flags &= ~(EV_EOF | EV_NODATA);
459 	lwkt_reltoken(&vp->v_token);
460 	return (kn->kn_data >= so->so_snd.ssb_lowat);
461 }
462 
463 /*
464  * fifo_inactive(struct vnode *a_vp)
465  */
466 static int
467 fifo_inactive(struct vop_inactive_args *ap)
468 {
469 	return (0);
470 }
471 
472 /*
473  * This is a noop, simply returning what one has been given.
474  *
475  * fifo_bmap(struct vnode *a_vp, off_t a_loffset,
476  *	     off_t *a_doffsetp, int *a_runp, int *a_runb)
477  */
478 static int
479 fifo_bmap(struct vop_bmap_args *ap)
480 {
481 	if (ap->a_doffsetp != NULL)
482 		*ap->a_doffsetp = ap->a_loffset;
483 	if (ap->a_runp != NULL)
484 		*ap->a_runp = 0;
485 	if (ap->a_runb != NULL)
486 		*ap->a_runb = 0;
487 	return (0);
488 }
489 
490 /*
491  * Device close routine
492  *
493  * fifo_close(struct vnode *a_vp, int a_fflag)
494  */
495 /* ARGSUSED */
496 static int
497 fifo_close(struct vop_close_args *ap)
498 {
499 	struct vnode *vp = ap->a_vp;
500 	struct fifoinfo *fip;
501 	int error1, error2;
502 
503 	lwkt_gettoken(&vp->v_token);
504 	fip = vp->v_fifoinfo;
505 	if (ap->a_fflag & FREAD) {
506 		fip->fi_readers--;
507 		if (fip->fi_readers == 0)
508 			soisdisconnected(fip->fi_writesock);
509 	}
510 	if (ap->a_fflag & FWRITE) {
511 		fip->fi_writers--;
512 		if (fip->fi_writers == 0)
513 			soisdisconnected(fip->fi_readsock);
514 	}
515 	if (vp->v_sysref.refcnt > 1) {
516 		vop_stdclose(ap);
517 		lwkt_reltoken(&vp->v_token);
518 		return (0);
519 	}
520 	error1 = soclose(fip->fi_readsock, FNONBLOCK);
521 	error2 = soclose(fip->fi_writesock, FNONBLOCK);
522 	kfree(fip, M_FIFOINFO);
523 	vp->v_fifoinfo = NULL;
524 	if (error1) {
525 		error2 = error1;
526 	} else {
527 		vop_stdclose(ap);
528 	}
529 	lwkt_reltoken(&vp->v_token);
530 	return (error2);
531 }
532 
533 
534 /*
535  * Print out internal contents of a fifo vnode.
536  */
537 int
538 fifo_printinfo(struct vnode *vp)
539 {
540 	struct fifoinfo *fip = vp->v_fifoinfo;
541 
542 	kprintf(", fifo with %ld readers and %ld writers",
543 		fip->fi_readers, fip->fi_writers);
544 	return (0);
545 }
546 
547 /*
548  * Print out the contents of a fifo vnode.
549  *
550  * fifo_print(struct vnode *a_vp)
551  */
552 static int
553 fifo_print(struct vop_print_args *ap)
554 {
555 	kprintf("tag VT_NON");
556 	fifo_printinfo(ap->a_vp);
557 	kprintf("\n");
558 	return (0);
559 }
560 
561 /*
562  * Return POSIX pathconf information applicable to fifo's.
563  *
564  * fifo_pathconf(struct vnode *a_vp, int a_name, int *a_retval)
565  */
566 int
567 fifo_pathconf(struct vop_pathconf_args *ap)
568 {
569 	switch (ap->a_name) {
570 	case _PC_LINK_MAX:
571 		*ap->a_retval = LINK_MAX;
572 		return (0);
573 	case _PC_PIPE_BUF:
574 		*ap->a_retval = PIPE_BUF;
575 		return (0);
576 	case _PC_CHOWN_RESTRICTED:
577 		*ap->a_retval = 1;
578 		return (0);
579 	default:
580 		return (EINVAL);
581 	}
582 	/* NOTREACHED */
583 }
584 
585 /*
586  * Fifo advisory byte-level locks.
587  *
588  * fifo_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl,
589  *		int a_flags)
590  */
591 /* ARGSUSED */
592 static int
593 fifo_advlock(struct vop_advlock_args *ap)
594 {
595 	return ((ap->a_flags & F_POSIX) ? EINVAL : EOPNOTSUPP);
596 }
597 
598 /*
599  * Fifo bad operation
600  */
601 static int
602 fifo_badop(void)
603 {
604 	panic("fifo_badop called");
605 	/* NOTREACHED */
606 }
607