1 /* $OpenBSD: fifo_vnops.c,v 1.93 2022/02/16 13:19:33 visa 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/systm.h> 37 #include <sys/time.h> 38 #include <sys/namei.h> 39 #include <sys/vnode.h> 40 #include <sys/lock.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/stat.h> 45 #include <sys/ioctl.h> 46 #include <sys/fcntl.h> 47 #include <sys/file.h> 48 #include <sys/event.h> 49 #include <sys/errno.h> 50 #include <sys/malloc.h> 51 #include <sys/poll.h> 52 #include <sys/unistd.h> 53 54 #include <miscfs/fifofs/fifo.h> 55 56 /* 57 * This structure is associated with the FIFO vnode and stores 58 * the state associated with the FIFO. 59 */ 60 struct fifoinfo { 61 struct socket *fi_readsock; 62 struct socket *fi_writesock; 63 long fi_readers; 64 long fi_writers; 65 }; 66 67 const struct vops fifo_vops = { 68 .vop_lookup = vop_generic_lookup, 69 .vop_create = vop_generic_badop, 70 .vop_mknod = vop_generic_badop, 71 .vop_open = fifo_open, 72 .vop_close = fifo_close, 73 .vop_access = fifo_ebadf, 74 .vop_getattr = fifo_ebadf, 75 .vop_setattr = fifo_ebadf, 76 .vop_read = fifo_read, 77 .vop_write = fifo_write, 78 .vop_ioctl = fifo_ioctl, 79 .vop_poll = fifo_poll, 80 .vop_kqfilter = fifo_kqfilter, 81 .vop_revoke = vop_generic_revoke, 82 .vop_fsync = nullop, 83 .vop_remove = vop_generic_badop, 84 .vop_link = vop_generic_badop, 85 .vop_rename = vop_generic_badop, 86 .vop_mkdir = vop_generic_badop, 87 .vop_rmdir = vop_generic_badop, 88 .vop_symlink = vop_generic_badop, 89 .vop_readdir = vop_generic_badop, 90 .vop_readlink = vop_generic_badop, 91 .vop_abortop = vop_generic_badop, 92 .vop_inactive = fifo_inactive, 93 .vop_reclaim = fifo_reclaim, 94 .vop_lock = nullop, 95 .vop_unlock = nullop, 96 .vop_islocked = nullop, 97 .vop_bmap = vop_generic_bmap, 98 .vop_strategy = vop_generic_badop, 99 .vop_print = fifo_print, 100 .vop_pathconf = fifo_pathconf, 101 .vop_advlock = fifo_advlock, 102 .vop_bwrite = nullop 103 }; 104 105 void filt_fifordetach(struct knote *kn); 106 int filt_fiforead(struct knote *kn, long hint); 107 void filt_fifowdetach(struct knote *kn); 108 int filt_fifowrite(struct knote *kn, long hint); 109 int filt_fifoexcept(struct knote *kn, long hint); 110 int filt_fifomodify(struct kevent *kev, struct knote *kn); 111 int filt_fifoprocess(struct knote *kn, struct kevent *kev); 112 113 const struct filterops fiforead_filtops = { 114 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 115 .f_attach = NULL, 116 .f_detach = filt_fifordetach, 117 .f_event = filt_fiforead, 118 .f_modify = filt_fifomodify, 119 .f_process = filt_fifoprocess, 120 }; 121 122 const struct filterops fifowrite_filtops = { 123 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 124 .f_attach = NULL, 125 .f_detach = filt_fifowdetach, 126 .f_event = filt_fifowrite, 127 .f_modify = filt_fifomodify, 128 .f_process = filt_fifoprocess, 129 }; 130 131 const struct filterops fifoexcept_filtops = { 132 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 133 .f_attach = NULL, 134 .f_detach = filt_fifordetach, 135 .f_event = filt_fifoexcept, 136 .f_modify = filt_fifomodify, 137 .f_process = filt_fifoprocess, 138 }; 139 140 /* 141 * Open called to set up a new instance of a fifo or 142 * to find an active instance of a fifo. 143 */ 144 /* ARGSUSED */ 145 int 146 fifo_open(void *v) 147 { 148 struct vop_open_args *ap = v; 149 struct vnode *vp = ap->a_vp; 150 struct fifoinfo *fip; 151 struct socket *rso, *wso; 152 int s, error; 153 154 if ((fip = vp->v_fifoinfo) == NULL) { 155 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 156 vp->v_fifoinfo = fip; 157 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) { 158 free(fip, M_VNODE, sizeof *fip); 159 vp->v_fifoinfo = NULL; 160 return (error); 161 } 162 fip->fi_readsock = rso; 163 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) { 164 (void)soclose(rso, 0); 165 free(fip, M_VNODE, sizeof *fip); 166 vp->v_fifoinfo = NULL; 167 return (error); 168 } 169 fip->fi_writesock = wso; 170 if ((error = soconnect2(wso, rso)) != 0) { 171 (void)soclose(wso, 0); 172 (void)soclose(rso, 0); 173 free(fip, M_VNODE, sizeof *fip); 174 vp->v_fifoinfo = NULL; 175 return (error); 176 } 177 fip->fi_readers = fip->fi_writers = 0; 178 s = solock(wso); 179 wso->so_state |= SS_CANTSENDMORE; 180 wso->so_snd.sb_lowat = PIPE_BUF; 181 } else { 182 rso = fip->fi_readsock; 183 wso = fip->fi_writesock; 184 s = solock(wso); 185 } 186 if (ap->a_mode & FREAD) { 187 fip->fi_readers++; 188 if (fip->fi_readers == 1) { 189 wso->so_state &= ~SS_CANTSENDMORE; 190 if (fip->fi_writers > 0) 191 wakeup(&fip->fi_writers); 192 } 193 } 194 if (ap->a_mode & FWRITE) { 195 fip->fi_writers++; 196 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { 197 error = ENXIO; 198 sounlock(wso, s); 199 goto bad; 200 } 201 if (fip->fi_writers == 1) { 202 rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED); 203 if (fip->fi_readers > 0) 204 wakeup(&fip->fi_readers); 205 } 206 } 207 sounlock(wso, s); 208 if ((ap->a_mode & O_NONBLOCK) == 0) { 209 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { 210 VOP_UNLOCK(vp); 211 error = tsleep_nsec(&fip->fi_readers, 212 PCATCH | PSOCK, "fifor", INFSLP); 213 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 214 if (error) 215 goto bad; 216 } 217 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { 218 VOP_UNLOCK(vp); 219 error = tsleep_nsec(&fip->fi_writers, 220 PCATCH | PSOCK, "fifow", INFSLP); 221 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 222 if (error) 223 goto bad; 224 } 225 } 226 return (0); 227 bad: 228 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 229 return (error); 230 } 231 232 /* 233 * Vnode op for read 234 */ 235 /* ARGSUSED */ 236 int 237 fifo_read(void *v) 238 { 239 struct vop_read_args *ap = v; 240 struct uio *uio = ap->a_uio; 241 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 242 int error, flags = 0; 243 244 #ifdef DIAGNOSTIC 245 if (uio->uio_rw != UIO_READ) 246 panic("fifo_read mode"); 247 #endif 248 if (uio->uio_resid == 0) 249 return (0); 250 if (ap->a_ioflag & IO_NDELAY) 251 flags |= MSG_DONTWAIT; 252 VOP_UNLOCK(ap->a_vp); 253 error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0); 254 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 255 if (ap->a_ioflag & IO_NDELAY) { 256 if (error == EWOULDBLOCK && 257 ap->a_vp->v_fifoinfo->fi_writers == 0) 258 error = 0; 259 } 260 return (error); 261 } 262 263 /* 264 * Vnode op for write 265 */ 266 /* ARGSUSED */ 267 int 268 fifo_write(void *v) 269 { 270 struct vop_write_args *ap = v; 271 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 272 int error, flags = 0; 273 274 #ifdef DIAGNOSTIC 275 if (ap->a_uio->uio_rw != UIO_WRITE) 276 panic("fifo_write mode"); 277 #endif 278 if (ap->a_ioflag & IO_NDELAY) 279 flags |= MSG_DONTWAIT; 280 VOP_UNLOCK(ap->a_vp); 281 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags); 282 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 283 return (error); 284 } 285 286 /* 287 * Device ioctl operation. 288 */ 289 /* ARGSUSED */ 290 int 291 fifo_ioctl(void *v) 292 { 293 struct vop_ioctl_args *ap = v; 294 struct file filetmp; 295 int error; 296 297 if (ap->a_command == FIONBIO) 298 return (0); 299 if (ap->a_fflag & FREAD) { 300 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 301 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 302 if (error) 303 return (error); 304 } 305 if (ap->a_fflag & FWRITE) { 306 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 307 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 308 if (error) 309 return (error); 310 } 311 return (0); 312 } 313 314 /* ARGSUSED */ 315 int 316 fifo_poll(void *v) 317 { 318 struct vop_poll_args *ap = v; 319 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 320 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 321 int events = 0; 322 int revents = 0; 323 int s; 324 325 /* 326 * FIFOs don't support out-of-band or high priority data. 327 */ 328 s = solock(rso); 329 if (ap->a_fflag & FREAD) 330 events |= ap->a_events & (POLLIN | POLLRDNORM); 331 if (ap->a_fflag & FWRITE) 332 events |= ap->a_events & (POLLOUT | POLLWRNORM); 333 334 if (events & (POLLIN | POLLRDNORM)) { 335 if (soreadable(rso)) 336 revents |= events & (POLLIN | POLLRDNORM); 337 } 338 /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ 339 if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLL_NOHUP)) { 340 revents |= POLLHUP; 341 } else if (events & (POLLOUT | POLLWRNORM)) { 342 if (sowriteable(wso)) 343 revents |= events & (POLLOUT | POLLWRNORM); 344 } 345 if (revents == 0) { 346 /* We want to return POLLHUP even if no valid events set. */ 347 if (events == 0 && !(ap->a_events & POLL_NOHUP)) 348 events = POLLIN; 349 if (events & (POLLIN | POLLRDNORM)) { 350 selrecord(ap->a_p, &rso->so_rcv.sb_sel); 351 rso->so_rcv.sb_flags |= SB_SEL; 352 } 353 if (events & (POLLOUT | POLLWRNORM)) { 354 selrecord(ap->a_p, &wso->so_snd.sb_sel); 355 wso->so_snd.sb_flags |= SB_SEL; 356 } 357 } 358 sounlock(rso, s); 359 return (revents); 360 } 361 362 int 363 fifo_inactive(void *v) 364 { 365 struct vop_inactive_args *ap = v; 366 367 VOP_UNLOCK(ap->a_vp); 368 return (0); 369 } 370 371 372 /* 373 * Device close routine 374 */ 375 /* ARGSUSED */ 376 int 377 fifo_close(void *v) 378 { 379 struct vop_close_args *ap = v; 380 struct vnode *vp = ap->a_vp; 381 struct fifoinfo *fip = vp->v_fifoinfo; 382 int s, error1 = 0, error2 = 0; 383 384 if (fip == NULL) 385 return (0); 386 387 if (ap->a_fflag & FREAD) { 388 if (--fip->fi_readers == 0) { 389 struct socket *wso = fip->fi_writesock; 390 391 s = solock(wso); 392 socantsendmore(wso); 393 sounlock(wso, s); 394 } 395 } 396 if (ap->a_fflag & FWRITE) { 397 if (--fip->fi_writers == 0) { 398 struct socket *rso = fip->fi_readsock; 399 400 s = solock(rso); 401 /* SS_ISDISCONNECTED will result in POLLHUP */ 402 rso->so_state |= SS_ISDISCONNECTED; 403 socantrcvmore(rso); 404 sounlock(rso, s); 405 } 406 } 407 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 408 error1 = soclose(fip->fi_readsock, 0); 409 error2 = soclose(fip->fi_writesock, 0); 410 free(fip, M_VNODE, sizeof *fip); 411 vp->v_fifoinfo = NULL; 412 } 413 return (error1 ? error1 : error2); 414 } 415 416 int 417 fifo_reclaim(void *v) 418 { 419 struct vop_reclaim_args *ap = v; 420 struct vnode *vp = ap->a_vp; 421 struct fifoinfo *fip = vp->v_fifoinfo; 422 423 if (fip == NULL) 424 return (0); 425 426 soclose(fip->fi_readsock, 0); 427 soclose(fip->fi_writesock, 0); 428 free(fip, M_VNODE, sizeof *fip); 429 vp->v_fifoinfo = NULL; 430 431 return (0); 432 } 433 434 /* 435 * Print out the contents of a fifo vnode. 436 */ 437 int 438 fifo_print(void *v) 439 { 440 struct vop_print_args *ap = v; 441 442 printf("tag VT_NON"); 443 fifo_printinfo(ap->a_vp); 444 printf("\n"); 445 return 0; 446 } 447 448 /* 449 * Print out internal contents of a fifo vnode. 450 */ 451 void 452 fifo_printinfo(struct vnode *vp) 453 { 454 struct fifoinfo *fip = vp->v_fifoinfo; 455 456 printf(", fifo with %ld readers and %ld writers", 457 fip->fi_readers, fip->fi_writers); 458 } 459 460 /* 461 * Return POSIX pathconf information applicable to fifo's. 462 */ 463 int 464 fifo_pathconf(void *v) 465 { 466 struct vop_pathconf_args *ap = v; 467 int error = 0; 468 469 switch (ap->a_name) { 470 case _PC_LINK_MAX: 471 *ap->a_retval = LINK_MAX; 472 break; 473 case _PC_CHOWN_RESTRICTED: 474 *ap->a_retval = 1; 475 break; 476 case _PC_TIMESTAMP_RESOLUTION: 477 *ap->a_retval = 1; 478 break; 479 default: 480 error = EINVAL; 481 break; 482 } 483 484 return (error); 485 } 486 487 /* 488 * Fifo failed operation 489 */ 490 /*ARGSUSED*/ 491 int 492 fifo_ebadf(void *v) 493 { 494 495 return (EBADF); 496 } 497 498 /* 499 * Fifo advisory byte-level locks. 500 */ 501 /* ARGSUSED */ 502 int 503 fifo_advlock(void *v) 504 { 505 return (EOPNOTSUPP); 506 } 507 508 int 509 fifo_kqfilter(void *v) 510 { 511 struct vop_kqfilter_args *ap = v; 512 struct fifoinfo *fip = ap->a_vp->v_fifoinfo; 513 struct sockbuf *sb; 514 struct socket *so; 515 516 switch (ap->a_kn->kn_filter) { 517 case EVFILT_READ: 518 if (!(ap->a_fflag & FREAD)) 519 return (EINVAL); 520 ap->a_kn->kn_fop = &fiforead_filtops; 521 so = fip->fi_readsock; 522 sb = &so->so_rcv; 523 break; 524 case EVFILT_WRITE: 525 if (!(ap->a_fflag & FWRITE)) { 526 /* Tell upper layer to ask for POLLUP only */ 527 if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT)) 528 return (EPERM); 529 return (EINVAL); 530 } 531 ap->a_kn->kn_fop = &fifowrite_filtops; 532 so = fip->fi_writesock; 533 sb = &so->so_snd; 534 break; 535 case EVFILT_EXCEPT: 536 if (ap->a_kn->kn_flags & __EV_SELECT) { 537 /* Prevent triggering exceptfds. */ 538 return (EPERM); 539 } 540 if ((ap->a_kn->kn_flags & __EV_POLL) == 0) { 541 /* Disallow usage through kevent(2). */ 542 return (EINVAL); 543 } 544 ap->a_kn->kn_fop = &fifoexcept_filtops; 545 so = fip->fi_readsock; 546 sb = &so->so_rcv; 547 break; 548 default: 549 return (EINVAL); 550 } 551 552 ap->a_kn->kn_hook = so; 553 554 klist_insert(&sb->sb_sel.si_note, ap->a_kn); 555 556 return (0); 557 } 558 559 void 560 filt_fifordetach(struct knote *kn) 561 { 562 struct socket *so = (struct socket *)kn->kn_hook; 563 564 klist_remove(&so->so_rcv.sb_sel.si_note, kn); 565 } 566 567 int 568 filt_fiforead(struct knote *kn, long hint) 569 { 570 struct socket *so = kn->kn_hook; 571 int rv; 572 573 soassertlocked(so); 574 575 kn->kn_data = so->so_rcv.sb_cc; 576 if (so->so_state & SS_CANTRCVMORE) { 577 kn->kn_flags |= EV_EOF; 578 if (kn->kn_flags & __EV_POLL) { 579 if (so->so_state & SS_ISDISCONNECTED) 580 kn->kn_flags |= __EV_HUP; 581 else 582 kn->kn_flags &= ~__EV_HUP; 583 } 584 rv = 1; 585 } else { 586 kn->kn_flags &= ~(EV_EOF | __EV_HUP); 587 rv = (kn->kn_data > 0); 588 } 589 590 return (rv); 591 } 592 593 void 594 filt_fifowdetach(struct knote *kn) 595 { 596 struct socket *so = (struct socket *)kn->kn_hook; 597 598 klist_remove(&so->so_snd.sb_sel.si_note, kn); 599 } 600 601 int 602 filt_fifowrite(struct knote *kn, long hint) 603 { 604 struct socket *so = kn->kn_hook; 605 int rv; 606 607 soassertlocked(so); 608 609 kn->kn_data = sbspace(so, &so->so_snd); 610 if (so->so_state & SS_CANTSENDMORE) { 611 kn->kn_flags |= EV_EOF; 612 rv = 1; 613 } else { 614 kn->kn_flags &= ~EV_EOF; 615 rv = (kn->kn_data >= so->so_snd.sb_lowat); 616 } 617 618 return (rv); 619 } 620 621 int 622 filt_fifoexcept(struct knote *kn, long hint) 623 { 624 struct socket *so = kn->kn_hook; 625 int rv = 0; 626 627 soassertlocked(so); 628 629 if (kn->kn_flags & __EV_POLL) { 630 if (so->so_state & SS_ISDISCONNECTED) { 631 kn->kn_flags |= __EV_HUP; 632 rv = 1; 633 } else { 634 kn->kn_flags &= ~__EV_HUP; 635 } 636 } 637 638 return (rv); 639 } 640 641 int 642 filt_fifomodify(struct kevent *kev, struct knote *kn) 643 { 644 struct socket *so = kn->kn_hook; 645 int rv, s; 646 647 s = solock(so); 648 rv = knote_modify(kev, kn); 649 sounlock(so, s); 650 651 return (rv); 652 } 653 654 int 655 filt_fifoprocess(struct knote *kn, struct kevent *kev) 656 { 657 struct socket *so = kn->kn_hook; 658 int rv, s; 659 660 s = solock(so); 661 rv = knote_process(kn, kev); 662 sounlock(so, s); 663 664 return (rv); 665 } 666