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