1 /* $OpenBSD: fifo_vnops.c,v 1.21 2004/05/18 12:37:51 pedro 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, vn_default_error },
67 { &vop_lookup_desc, fifo_lookup }, /* lookup */
68 { &vop_create_desc, fifo_create }, /* create */
69 { &vop_mknod_desc, fifo_mknod }, /* mknod */
70 { &vop_open_desc, fifo_open }, /* open */
71 { &vop_close_desc, fifo_close }, /* close */
72 { &vop_access_desc, fifo_access }, /* access */
73 { &vop_getattr_desc, fifo_getattr }, /* getattr */
74 { &vop_setattr_desc, fifo_setattr }, /* setattr */
75 { &vop_read_desc, fifo_read }, /* read */
76 { &vop_write_desc, fifo_write }, /* write */
77 { &vop_lease_desc, fifo_lease_check }, /* lease */
78 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
79 { &vop_poll_desc, fifo_poll }, /* poll */
80 { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */
81 { &vop_revoke_desc, fifo_revoke }, /* revoke */
82 { &vop_fsync_desc, fifo_fsync }, /* fsync */
83 { &vop_remove_desc, fifo_remove }, /* remove */
84 { &vop_link_desc, fifo_link }, /* link */
85 { &vop_rename_desc, fifo_rename }, /* rename */
86 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */
87 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */
88 { &vop_symlink_desc, fifo_symlink }, /* symlink */
89 { &vop_readdir_desc, fifo_readdir }, /* readdir */
90 { &vop_readlink_desc, fifo_readlink }, /* readlink */
91 { &vop_abortop_desc, fifo_abortop }, /* abortop */
92 { &vop_inactive_desc, fifo_inactive }, /* inactive */
93 { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */
94 { &vop_lock_desc, fifo_lock }, /* lock */
95 { &vop_unlock_desc, fifo_unlock }, /* unlock */
96 { &vop_bmap_desc, fifo_bmap }, /* bmap */
97 { &vop_strategy_desc, fifo_strategy }, /* strategy */
98 { &vop_print_desc, fifo_print }, /* print */
99 { &vop_islocked_desc, fifo_islocked }, /* islocked */
100 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
101 { &vop_advlock_desc, fifo_advlock }, /* advlock */
102 { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */
103 { NULL, NULL }
104 };
105
106 struct vnodeopv_desc fifo_vnodeop_opv_desc =
107 { &fifo_vnodeop_p, fifo_vnodeop_entries };
108
109 int
fifo_vnoperate(void * v)110 fifo_vnoperate(void *v)
111 {
112 struct vop_generic_args *ap = v;
113
114 return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
115 }
116
117 void filt_fifordetach(struct knote *kn);
118 int filt_fiforead(struct knote *kn, long hint);
119 void filt_fifowdetach(struct knote *kn);
120 int filt_fifowrite(struct knote *kn, long hint);
121
122 struct filterops fiforead_filtops =
123 { 1, NULL, filt_fifordetach, filt_fiforead };
124 struct filterops fifowrite_filtops =
125 { 1, NULL, filt_fifowdetach, filt_fifowrite };
126
127 /*
128 * Trivial lookup routine that always fails.
129 */
130 /* ARGSUSED */
131 int
fifo_lookup(v)132 fifo_lookup(v)
133 void *v;
134 {
135 struct vop_lookup_args /* {
136 struct vnode * a_dvp;
137 struct vnode ** a_vpp;
138 struct componentname * a_cnp;
139 } */ *ap = v;
140
141 *ap->a_vpp = NULL;
142 return (ENOTDIR);
143 }
144
145 /*
146 * Open called to set up a new instance of a fifo or
147 * to find an active instance of a fifo.
148 */
149 /* ARGSUSED */
150 int
fifo_open(v)151 fifo_open(v)
152 void *v;
153 {
154 struct vop_open_args /* {
155 struct vnode *a_vp;
156 int a_mode;
157 struct ucred *a_cred;
158 struct proc *a_p;
159 } */ *ap = v;
160 register struct vnode *vp = ap->a_vp;
161 register struct fifoinfo *fip;
162 struct proc *p = ap->a_p;
163 struct socket *rso, *wso;
164 int error;
165
166 if ((fip = vp->v_fifoinfo) == NULL) {
167 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
168 vp->v_fifoinfo = fip;
169 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
170 free(fip, M_VNODE);
171 vp->v_fifoinfo = NULL;
172 return (error);
173 }
174 fip->fi_readsock = rso;
175 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
176 (void)soclose(rso);
177 free(fip, M_VNODE);
178 vp->v_fifoinfo = NULL;
179 return (error);
180 }
181 fip->fi_writesock = wso;
182 if ((error = unp_connect2(wso, rso)) != 0) {
183 (void)soclose(wso);
184 (void)soclose(rso);
185 free(fip, M_VNODE);
186 vp->v_fifoinfo = NULL;
187 return (error);
188 }
189 fip->fi_readers = fip->fi_writers = 0;
190 wso->so_snd.sb_lowat = PIPE_BUF;
191 rso->so_state |= SS_CANTRCVMORE;
192 }
193 if (ap->a_mode & FREAD) {
194 fip->fi_readers++;
195 if (fip->fi_readers == 1) {
196 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
197 if (fip->fi_writers > 0)
198 wakeup(&fip->fi_writers);
199 }
200 }
201 if (ap->a_mode & FWRITE) {
202 fip->fi_writers++;
203 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
204 error = ENXIO;
205 goto bad;
206 }
207 if (fip->fi_writers == 1) {
208 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
209 if (fip->fi_readers > 0)
210 wakeup(&fip->fi_readers);
211 }
212 }
213 if ((ap->a_mode & O_NONBLOCK) == 0) {
214 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
215 VOP_UNLOCK(vp, 0, p);
216 error = tsleep(&fip->fi_readers,
217 PCATCH | PSOCK, "fifor", 0);
218 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
219 if (error)
220 goto bad;
221 }
222 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
223 VOP_UNLOCK(vp, 0, p);
224 error = tsleep(&fip->fi_writers,
225 PCATCH | PSOCK, "fifow", 0);
226 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
227 if (error)
228 goto bad;
229 }
230 }
231 return (0);
232 bad:
233 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
234 return (error);
235 }
236
237 /*
238 * Vnode op for read
239 */
240 /* ARGSUSED */
241 int
fifo_read(v)242 fifo_read(v)
243 void *v;
244 {
245 struct vop_read_args /* {
246 struct vnode *a_vp;
247 struct uio *a_uio;
248 int a_ioflag;
249 struct ucred *a_cred;
250 } */ *ap = v;
251 register struct uio *uio = ap->a_uio;
252 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
253 struct proc *p = uio->uio_procp;
254 int error;
255
256 #ifdef DIAGNOSTIC
257 if (uio->uio_rw != UIO_READ)
258 panic("fifo_read mode");
259 #endif
260 if (uio->uio_resid == 0)
261 return (0);
262 if (ap->a_ioflag & IO_NDELAY)
263 rso->so_state |= SS_NBIO;
264 VOP_UNLOCK(ap->a_vp, 0, p);
265 error = soreceive(rso, NULL, uio, NULL, NULL, NULL);
266 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
267 if (ap->a_ioflag & IO_NDELAY) {
268 rso->so_state &= ~SS_NBIO;
269 if (error == EWOULDBLOCK &&
270 ap->a_vp->v_fifoinfo->fi_writers == 0)
271 error = 0;
272 }
273 return (error);
274 }
275
276 /*
277 * Vnode op for write
278 */
279 /* ARGSUSED */
280 int
fifo_write(v)281 fifo_write(v)
282 void *v;
283 {
284 struct vop_write_args /* {
285 struct vnode *a_vp;
286 struct uio *a_uio;
287 int a_ioflag;
288 struct ucred *a_cred;
289 } */ *ap = v;
290 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
291 struct proc *p = ap->a_uio->uio_procp;
292 int error;
293
294 #ifdef DIAGNOSTIC
295 if (ap->a_uio->uio_rw != UIO_WRITE)
296 panic("fifo_write mode");
297 #endif
298 if (ap->a_ioflag & IO_NDELAY)
299 wso->so_state |= SS_NBIO;
300 VOP_UNLOCK(ap->a_vp, 0, p);
301 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
302 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
303 if (ap->a_ioflag & IO_NDELAY)
304 wso->so_state &= ~SS_NBIO;
305 return (error);
306 }
307
308 /*
309 * Device ioctl operation.
310 */
311 /* ARGSUSED */
312 int
fifo_ioctl(v)313 fifo_ioctl(v)
314 void *v;
315 {
316 struct vop_ioctl_args /* {
317 struct vnode *a_vp;
318 u_long a_command;
319 caddr_t a_data;
320 int a_fflag;
321 struct ucred *a_cred;
322 struct proc *a_p;
323 } */ *ap = v;
324 struct file filetmp;
325 int error;
326
327 if (ap->a_command == FIONBIO)
328 return (0);
329 if (ap->a_fflag & FREAD) {
330 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
331 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
332 if (error)
333 return (error);
334 }
335 if (ap->a_fflag & FWRITE) {
336 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
337 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
338 if (error)
339 return (error);
340 }
341 return (0);
342 }
343
344 /* ARGSUSED */
345 int
fifo_poll(v)346 fifo_poll(v)
347 void *v;
348 {
349 struct vop_poll_args /* {
350 struct vnode *a_vp;
351 int a_events;
352 struct proc *a_p;
353 } */ *ap = v;
354 struct file filetmp;
355 short ostate;
356 int revents = 0;
357
358 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
359 /*
360 * Socket and FIFO poll(2) semantics differ wrt EOF on read.
361 * Unlike a normal socket, FIFOs don't care whether or not
362 * SS_CANTRCVMORE is set. To get the correct semantics we
363 * must clear SS_CANTRCVMORE from so_state temporarily.
364 */
365 ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
366 if (ap->a_events & (POLLIN | POLLRDNORM))
367 ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
368 ~SS_CANTRCVMORE;
369 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
370 if (filetmp.f_data)
371 revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
372 ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
373 }
374 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
375 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
376 if (filetmp.f_data)
377 revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
378 }
379 return (revents);
380 }
381
382 int
fifo_inactive(v)383 fifo_inactive(v)
384 void *v;
385 {
386 struct vop_inactive_args /* {
387 struct vnode *a_vp;
388 struct proc *a_p;
389 } */ *ap = v;
390
391 VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
392 return (0);
393 }
394
395 /*
396 * This is a noop, simply returning what one has been given.
397 */
398 int
fifo_bmap(v)399 fifo_bmap(v)
400 void *v;
401 {
402 struct vop_bmap_args /* {
403 struct vnode *a_vp;
404 daddr_t a_bn;
405 struct vnode **a_vpp;
406 daddr_t *a_bnp;
407 int *a_runp;
408 } */ *ap = v;
409
410 if (ap->a_vpp != NULL)
411 *ap->a_vpp = ap->a_vp;
412 if (ap->a_bnp != NULL)
413 *ap->a_bnp = ap->a_bn;
414 return (0);
415 }
416
417 /*
418 * Device close routine
419 */
420 /* ARGSUSED */
421 int
fifo_close(v)422 fifo_close(v)
423 void *v;
424 {
425 struct vop_close_args /* {
426 struct vnode *a_vp;
427 int a_fflag;
428 struct ucred *a_cred;
429 struct proc *a_p;
430 } */ *ap = v;
431 register struct vnode *vp = ap->a_vp;
432 register struct fifoinfo *fip = vp->v_fifoinfo;
433 int error1 = 0, error2 = 0;
434
435 if (fip == NULL)
436 return (0);
437
438 if (ap->a_fflag & FREAD) {
439 if (--fip->fi_readers == 0)
440 socantsendmore(fip->fi_writesock);
441 }
442 if (ap->a_fflag & FWRITE) {
443 if (--fip->fi_writers == 0)
444 socantrcvmore(fip->fi_readsock);
445 }
446 if (fip->fi_readers == 0 && fip->fi_writers == 0) {
447 error1 = soclose(fip->fi_readsock);
448 error2 = soclose(fip->fi_writesock);
449 FREE(fip, M_VNODE);
450 vp->v_fifoinfo = NULL;
451 }
452 return (error1 ? error1 : error2);
453 }
454
455 int
fifo_reclaim(void * v)456 fifo_reclaim(void *v)
457 {
458 struct vop_reclaim_args *ap = v;
459 struct vnode *vp = ap->a_vp;
460 struct fifoinfo *fip = vp->v_fifoinfo;
461
462 if (fip == NULL)
463 return (0);
464
465 soclose(fip->fi_readsock);
466 soclose(fip->fi_writesock);
467 FREE(fip, M_VNODE);
468 vp->v_fifoinfo = NULL;
469
470 return (0);
471 }
472
473 /*
474 * Print out the contents of a fifo vnode.
475 */
476 int
fifo_print(v)477 fifo_print(v)
478 void *v;
479 {
480 struct vop_print_args /* {
481 struct vnode *a_vp;
482 } */ *ap = v;
483
484 printf("tag VT_NON");
485 fifo_printinfo(ap->a_vp);
486 printf("\n");
487 return 0;
488 }
489
490 /*
491 * Print out internal contents of a fifo vnode.
492 */
493 void
fifo_printinfo(vp)494 fifo_printinfo(vp)
495 struct vnode *vp;
496 {
497 register struct fifoinfo *fip = vp->v_fifoinfo;
498
499 printf(", fifo with %ld readers and %ld writers",
500 fip->fi_readers, fip->fi_writers);
501 }
502
503 /*
504 * Return POSIX pathconf information applicable to fifo's.
505 */
506 int
fifo_pathconf(v)507 fifo_pathconf(v)
508 void *v;
509 {
510 struct vop_pathconf_args /* {
511 struct vnode *a_vp;
512 int a_name;
513 register_t *a_retval;
514 } */ *ap = v;
515
516 switch (ap->a_name) {
517 case _PC_LINK_MAX:
518 *ap->a_retval = LINK_MAX;
519 return (0);
520 case _PC_PIPE_BUF:
521 *ap->a_retval = PIPE_BUF;
522 return (0);
523 case _PC_CHOWN_RESTRICTED:
524 *ap->a_retval = 1;
525 return (0);
526 default:
527 return (EINVAL);
528 }
529 /* NOTREACHED */
530 }
531
532 /*
533 * Fifo failed operation
534 */
535 /*ARGSUSED*/
536 int
fifo_ebadf(v)537 fifo_ebadf(v)
538 void *v;
539 {
540
541 return (EBADF);
542 }
543
544 /*
545 * Fifo advisory byte-level locks.
546 */
547 /* ARGSUSED */
548 int
fifo_advlock(v)549 fifo_advlock(v)
550 void *v;
551 {
552 return (EOPNOTSUPP);
553 }
554
555 /*
556 * Fifo bad operation
557 */
558 /*ARGSUSED*/
559 int
fifo_badop(v)560 fifo_badop(v)
561 void *v;
562 {
563
564 panic("fifo_badop called");
565 /* NOTREACHED */
566 return(0);
567 }
568
569
570 int
fifo_kqfilter(v)571 fifo_kqfilter(v)
572 void *v;
573 {
574 struct vop_kqfilter_args /* {
575 struct vnode *a_vp;
576 struct knote *a_kn;
577 } */ *ap = v;
578 struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
579 struct sockbuf *sb;
580
581 switch (ap->a_kn->kn_filter) {
582 case EVFILT_READ:
583 ap->a_kn->kn_fop = &fiforead_filtops;
584 sb = &so->so_rcv;
585 break;
586 case EVFILT_WRITE:
587 ap->a_kn->kn_fop = &fifowrite_filtops;
588 sb = &so->so_snd;
589 break;
590 default:
591 return (1);
592 }
593
594 ap->a_kn->kn_hook = so;
595
596 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
597 sb->sb_flags |= SB_KNOTE;
598
599 return (0);
600 }
601
602 void
filt_fifordetach(struct knote * kn)603 filt_fifordetach(struct knote *kn)
604 {
605 struct socket *so = (struct socket *)kn->kn_hook;
606
607 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
608 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
609 so->so_rcv.sb_flags &= ~SB_KNOTE;
610 }
611
612 int
filt_fiforead(struct knote * kn,long hint)613 filt_fiforead(struct knote *kn, long hint)
614 {
615 struct socket *so = (struct socket *)kn->kn_hook;
616
617 kn->kn_data = so->so_rcv.sb_cc;
618 if (so->so_state & SS_CANTRCVMORE) {
619 kn->kn_flags |= EV_EOF;
620 return (1);
621 }
622 kn->kn_flags &= ~EV_EOF;
623 return (kn->kn_data > 0);
624 }
625
626 void
filt_fifowdetach(struct knote * kn)627 filt_fifowdetach(struct knote *kn)
628 {
629 struct socket *so = (struct socket *)kn->kn_hook;
630
631 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
632 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
633 so->so_snd.sb_flags &= ~SB_KNOTE;
634 }
635
636 int
filt_fifowrite(struct knote * kn,long hint)637 filt_fifowrite(struct knote *kn, long hint)
638 {
639 struct socket *so = (struct socket *)kn->kn_hook;
640
641 kn->kn_data = sbspace(&so->so_snd);
642 if (so->so_state & SS_CANTSENDMORE) {
643 kn->kn_flags |= EV_EOF;
644 return (1);
645 }
646 kn->kn_flags &= ~EV_EOF;
647 return (kn->kn_data >= so->so_snd.sb_lowat);
648 }
649