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