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: src/sys/miscfs/fifofs/fifo_vnops.c,v 1.45.2.4 2003/04/22 10:11:24 bde Exp $ 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_kqfilter __P((struct vop_kqfilter_args *)); 75 static int fifo_inactive __P((struct vop_inactive_args *)); 76 static int fifo_bmap __P((struct vop_bmap_args *)); 77 static int fifo_pathconf __P((struct vop_pathconf_args *)); 78 static int fifo_advlock __P((struct vop_advlock_args *)); 79 80 static void filt_fifordetach(struct knote *kn); 81 static int filt_fiforead(struct knote *kn, long hint); 82 static void filt_fifowdetach(struct knote *kn); 83 static int filt_fifowrite(struct knote *kn, long hint); 84 85 static struct filterops fiforead_filtops = 86 { 1, NULL, filt_fifordetach, filt_fiforead }; 87 static struct filterops fifowrite_filtops = 88 { 1, NULL, filt_fifowdetach, filt_fifowrite }; 89 90 vop_t **fifo_vnodeop_p; 91 static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 92 { &vop_default_desc, (vop_t *) vop_defaultop }, 93 { &vop_access_desc, (vop_t *) vop_ebadf }, 94 { &vop_advlock_desc, (vop_t *) fifo_advlock }, 95 { &vop_bmap_desc, (vop_t *) fifo_bmap }, 96 { &vop_close_desc, (vop_t *) fifo_close }, 97 { &vop_create_desc, (vop_t *) fifo_badop }, 98 { &vop_getattr_desc, (vop_t *) vop_ebadf }, 99 { &vop_inactive_desc, (vop_t *) fifo_inactive }, 100 { &vop_ioctl_desc, (vop_t *) fifo_ioctl }, 101 { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter }, 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 sowwakeup(fip->fi_writesock); 213 } 214 } 215 } 216 if (ap->a_mode & FWRITE) { 217 fip->fi_writers++; 218 if (fip->fi_writers == 1) { 219 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 220 if (fip->fi_readers > 0) { 221 wakeup((caddr_t)&fip->fi_readers); 222 sorwakeup(fip->fi_writesock); 223 } 224 } 225 } 226 if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { 227 if (fip->fi_writers == 0) { 228 VOP_UNLOCK(vp, 0, p); 229 error = tsleep((caddr_t)&fip->fi_readers, 230 PCATCH | PSOCK, "fifoor", 0); 231 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 232 if (error) 233 goto bad; 234 /* 235 * We must have got woken up because we had a writer. 236 * That (and not still having one) is the condition 237 * that we must wait for. 238 */ 239 } 240 } 241 if (ap->a_mode & FWRITE) { 242 if (ap->a_mode & O_NONBLOCK) { 243 if (fip->fi_readers == 0) { 244 error = ENXIO; 245 goto bad; 246 } 247 } else { 248 if (fip->fi_readers == 0) { 249 VOP_UNLOCK(vp, 0, p); 250 error = tsleep((caddr_t)&fip->fi_writers, 251 PCATCH | PSOCK, "fifoow", 0); 252 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 253 if (error) 254 goto bad; 255 /* 256 * We must have got woken up because we had 257 * a reader. That (and not still having one) 258 * is the condition that we must wait for. 259 */ 260 } 261 } 262 } 263 return (0); 264 bad: 265 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p); 266 return (error); 267 } 268 269 /* 270 * Vnode op for read 271 */ 272 /* ARGSUSED */ 273 static int 274 fifo_read(ap) 275 struct vop_read_args /* { 276 struct vnode *a_vp; 277 struct uio *a_uio; 278 int a_ioflag; 279 struct ucred *a_cred; 280 } */ *ap; 281 { 282 struct uio *uio = ap->a_uio; 283 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 284 struct proc *p = uio->uio_procp; 285 int error, startresid; 286 287 #ifdef DIAGNOSTIC 288 if (uio->uio_rw != UIO_READ) 289 panic("fifo_read mode"); 290 #endif 291 if (uio->uio_resid == 0) 292 return (0); 293 if (ap->a_ioflag & IO_NDELAY) 294 rso->so_state |= SS_NBIO; 295 startresid = uio->uio_resid; 296 VOP_UNLOCK(ap->a_vp, 0, p); 297 error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, 298 (struct mbuf **)0, (int *)0); 299 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 300 if (ap->a_ioflag & IO_NDELAY) 301 rso->so_state &= ~SS_NBIO; 302 return (error); 303 } 304 305 /* 306 * Vnode op for write 307 */ 308 /* ARGSUSED */ 309 static int 310 fifo_write(ap) 311 struct vop_write_args /* { 312 struct vnode *a_vp; 313 struct uio *a_uio; 314 int a_ioflag; 315 struct ucred *a_cred; 316 } */ *ap; 317 { 318 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 319 struct proc *p = ap->a_uio->uio_procp; 320 int error; 321 322 #ifdef DIAGNOSTIC 323 if (ap->a_uio->uio_rw != UIO_WRITE) 324 panic("fifo_write mode"); 325 #endif 326 if (ap->a_ioflag & IO_NDELAY) 327 wso->so_state |= SS_NBIO; 328 VOP_UNLOCK(ap->a_vp, 0, p); 329 error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0, 330 (struct mbuf *)0, 0, p); 331 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 332 if (ap->a_ioflag & IO_NDELAY) 333 wso->so_state &= ~SS_NBIO; 334 return (error); 335 } 336 337 /* 338 * Device ioctl operation. 339 */ 340 /* ARGSUSED */ 341 static int 342 fifo_ioctl(ap) 343 struct vop_ioctl_args /* { 344 struct vnode *a_vp; 345 int a_command; 346 caddr_t a_data; 347 int a_fflag; 348 struct ucred *a_cred; 349 struct proc *a_p; 350 } */ *ap; 351 { 352 struct file filetmp; 353 int error; 354 355 if (ap->a_command == FIONBIO) 356 return (0); 357 if (ap->a_fflag & FREAD) { 358 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 359 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 360 if (error) 361 return (error); 362 } 363 if (ap->a_fflag & FWRITE) { 364 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 365 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 366 if (error) 367 return (error); 368 } 369 return (0); 370 } 371 372 /* ARGSUSED */ 373 static int 374 fifo_kqfilter(ap) 375 struct vop_kqfilter_args /* { 376 struct vnode *a_vp; 377 struct knote *a_kn; 378 } */ *ap; 379 { 380 struct fifoinfo *fi = ap->a_vp->v_fifoinfo; 381 struct socket *so; 382 struct sockbuf *sb; 383 384 switch (ap->a_kn->kn_filter) { 385 case EVFILT_READ: 386 ap->a_kn->kn_fop = &fiforead_filtops; 387 so = fi->fi_readsock; 388 sb = &so->so_rcv; 389 break; 390 case EVFILT_WRITE: 391 ap->a_kn->kn_fop = &fifowrite_filtops; 392 so = fi->fi_writesock; 393 sb = &so->so_snd; 394 break; 395 default: 396 return (1); 397 } 398 399 ap->a_kn->kn_hook = (caddr_t)so; 400 401 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext); 402 sb->sb_flags |= SB_KNOTE; 403 404 return (0); 405 } 406 407 static void 408 filt_fifordetach(struct knote *kn) 409 { 410 struct socket *so = (struct socket *)kn->kn_hook; 411 412 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); 413 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) 414 so->so_rcv.sb_flags &= ~SB_KNOTE; 415 } 416 417 static int 418 filt_fiforead(struct knote *kn, long hint) 419 { 420 struct socket *so = (struct socket *)kn->kn_hook; 421 422 kn->kn_data = so->so_rcv.sb_cc; 423 if (so->so_state & SS_CANTRCVMORE) { 424 kn->kn_flags |= EV_EOF; 425 return (1); 426 } 427 kn->kn_flags &= ~EV_EOF; 428 return (kn->kn_data > 0); 429 } 430 431 static void 432 filt_fifowdetach(struct knote *kn) 433 { 434 struct socket *so = (struct socket *)kn->kn_hook; 435 436 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); 437 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) 438 so->so_snd.sb_flags &= ~SB_KNOTE; 439 } 440 441 static int 442 filt_fifowrite(struct knote *kn, long hint) 443 { 444 struct socket *so = (struct socket *)kn->kn_hook; 445 446 kn->kn_data = sbspace(&so->so_snd); 447 if (so->so_state & SS_CANTSENDMORE) { 448 kn->kn_flags |= EV_EOF; 449 return (1); 450 } 451 kn->kn_flags &= ~EV_EOF; 452 return (kn->kn_data >= so->so_snd.sb_lowat); 453 } 454 455 /* ARGSUSED */ 456 static int 457 fifo_poll(ap) 458 struct vop_poll_args /* { 459 struct vnode *a_vp; 460 int a_events; 461 struct ucred *a_cred; 462 struct proc *a_p; 463 } */ *ap; 464 { 465 struct file filetmp; 466 int revents = 0; 467 468 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { 469 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 470 if (filetmp.f_data) 471 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred, 472 ap->a_p); 473 } 474 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { 475 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 476 if (filetmp.f_data) 477 revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred, 478 ap->a_p); 479 } 480 return (revents); 481 } 482 483 static int 484 fifo_inactive(ap) 485 struct vop_inactive_args /* { 486 struct vnode *a_vp; 487 struct proc *a_p; 488 } */ *ap; 489 { 490 491 VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 492 return (0); 493 } 494 495 /* 496 * This is a noop, simply returning what one has been given. 497 */ 498 static int 499 fifo_bmap(ap) 500 struct vop_bmap_args /* { 501 struct vnode *a_vp; 502 daddr_t a_bn; 503 struct vnode **a_vpp; 504 daddr_t *a_bnp; 505 int *a_runp; 506 int *a_runb; 507 } */ *ap; 508 { 509 510 if (ap->a_vpp != NULL) 511 *ap->a_vpp = ap->a_vp; 512 if (ap->a_bnp != NULL) 513 *ap->a_bnp = ap->a_bn; 514 if (ap->a_runp != NULL) 515 *ap->a_runp = 0; 516 if (ap->a_runb != NULL) 517 *ap->a_runb = 0; 518 return (0); 519 } 520 521 /* 522 * Device close routine 523 */ 524 /* ARGSUSED */ 525 static int 526 fifo_close(ap) 527 struct vop_close_args /* { 528 struct vnode *a_vp; 529 int a_fflag; 530 struct ucred *a_cred; 531 struct proc *a_p; 532 } */ *ap; 533 { 534 register struct vnode *vp = ap->a_vp; 535 register struct fifoinfo *fip = vp->v_fifoinfo; 536 int error1, error2; 537 538 if (ap->a_fflag & FREAD) { 539 fip->fi_readers--; 540 if (fip->fi_readers == 0) 541 socantsendmore(fip->fi_writesock); 542 } 543 if (ap->a_fflag & FWRITE) { 544 fip->fi_writers--; 545 if (fip->fi_writers == 0) 546 socantrcvmore(fip->fi_readsock); 547 } 548 if (vp->v_usecount > 1) 549 return (0); 550 error1 = soclose(fip->fi_readsock); 551 error2 = soclose(fip->fi_writesock); 552 FREE(fip, M_VNODE); 553 vp->v_fifoinfo = NULL; 554 if (error1) 555 return (error1); 556 return (error2); 557 } 558 559 560 /* 561 * Print out internal contents of a fifo vnode. 562 */ 563 int 564 fifo_printinfo(vp) 565 struct vnode *vp; 566 { 567 register struct fifoinfo *fip = vp->v_fifoinfo; 568 569 printf(", fifo with %ld readers and %ld writers", 570 fip->fi_readers, fip->fi_writers); 571 return (0); 572 } 573 574 /* 575 * Print out the contents of a fifo vnode. 576 */ 577 static int 578 fifo_print(ap) 579 struct vop_print_args /* { 580 struct vnode *a_vp; 581 } */ *ap; 582 { 583 584 printf("tag VT_NON"); 585 fifo_printinfo(ap->a_vp); 586 printf("\n"); 587 return (0); 588 } 589 590 /* 591 * Return POSIX pathconf information applicable to fifo's. 592 */ 593 int 594 fifo_pathconf(ap) 595 struct vop_pathconf_args /* { 596 struct vnode *a_vp; 597 int a_name; 598 int *a_retval; 599 } */ *ap; 600 { 601 602 switch (ap->a_name) { 603 case _PC_LINK_MAX: 604 *ap->a_retval = LINK_MAX; 605 return (0); 606 case _PC_PIPE_BUF: 607 *ap->a_retval = PIPE_BUF; 608 return (0); 609 case _PC_CHOWN_RESTRICTED: 610 *ap->a_retval = 1; 611 return (0); 612 default: 613 return (EINVAL); 614 } 615 /* NOTREACHED */ 616 } 617 618 /* 619 * Fifo advisory byte-level locks. 620 */ 621 /* ARGSUSED */ 622 static int 623 fifo_advlock(ap) 624 struct vop_advlock_args /* { 625 struct vnode *a_vp; 626 caddr_t a_id; 627 int a_op; 628 struct flock *a_fl; 629 int a_flags; 630 } */ *ap; 631 { 632 633 return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL); 634 } 635 636 /* 637 * Fifo bad operation 638 */ 639 static int 640 fifo_badop() 641 { 642 643 panic("fifo_badop called"); 644 /* NOTREACHED */ 645 } 646