1 /* $OpenBSD: fifo_vnops.c,v 1.83 2021/10/22 15:11:32 mpi 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 int filt_fiforeadmodify(struct kevent *kev, struct knote *kn); 108 int filt_fiforeadprocess(struct knote *kn, struct kevent *kev); 109 int filt_fiforead_common(struct knote *kn, struct socket *so); 110 void filt_fifowdetach(struct knote *kn); 111 int filt_fifowrite(struct knote *kn, long hint); 112 int filt_fifowritemodify(struct kevent *kev, struct knote *kn); 113 int filt_fifowriteprocess(struct knote *kn, struct kevent *kev); 114 int filt_fifowrite_common(struct knote *kn, struct socket *so); 115 int filt_fifoexcept(struct knote *kn, long hint); 116 int filt_fifoexceptmodify(struct kevent *kev, struct knote *kn); 117 int filt_fifoexceptprocess(struct knote *kn, struct kevent *kev); 118 int filt_fifoexcept_common(struct knote *kn, struct socket *so); 119 120 const struct filterops fiforead_filtops = { 121 .f_flags = FILTEROP_ISFD, 122 .f_attach = NULL, 123 .f_detach = filt_fifordetach, 124 .f_event = filt_fiforead, 125 .f_modify = filt_fiforeadmodify, 126 .f_process = filt_fiforeadprocess, 127 }; 128 129 const struct filterops fifowrite_filtops = { 130 .f_flags = FILTEROP_ISFD, 131 .f_attach = NULL, 132 .f_detach = filt_fifowdetach, 133 .f_event = filt_fifowrite, 134 .f_modify = filt_fifowritemodify, 135 .f_process = filt_fifowriteprocess, 136 }; 137 138 const struct filterops fifoexcept_filtops = { 139 .f_flags = FILTEROP_ISFD, 140 .f_attach = NULL, 141 .f_detach = filt_fifordetach, 142 .f_event = filt_fifoexcept, 143 .f_modify = filt_fifoexceptmodify, 144 .f_process = filt_fifoexceptprocess, 145 }; 146 147 /* 148 * Open called to set up a new instance of a fifo or 149 * to find an active instance of a fifo. 150 */ 151 /* ARGSUSED */ 152 int 153 fifo_open(void *v) 154 { 155 struct vop_open_args *ap = v; 156 struct vnode *vp = ap->a_vp; 157 struct fifoinfo *fip; 158 struct socket *rso, *wso; 159 int s, error; 160 161 if ((fip = vp->v_fifoinfo) == NULL) { 162 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 163 vp->v_fifoinfo = fip; 164 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) { 165 free(fip, M_VNODE, sizeof *fip); 166 vp->v_fifoinfo = NULL; 167 return (error); 168 } 169 fip->fi_readsock = rso; 170 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) { 171 (void)soclose(rso, 0); 172 free(fip, M_VNODE, sizeof *fip); 173 vp->v_fifoinfo = NULL; 174 return (error); 175 } 176 fip->fi_writesock = wso; 177 if ((error = soconnect2(wso, rso)) != 0) { 178 (void)soclose(wso, 0); 179 (void)soclose(rso, 0); 180 free(fip, M_VNODE, sizeof *fip); 181 vp->v_fifoinfo = NULL; 182 return (error); 183 } 184 fip->fi_readers = fip->fi_writers = 0; 185 s = solock(wso); 186 wso->so_state |= SS_CANTSENDMORE; 187 wso->so_snd.sb_lowat = PIPE_BUF; 188 } else { 189 rso = fip->fi_readsock; 190 wso = fip->fi_writesock; 191 s = solock(wso); 192 } 193 if (ap->a_mode & FREAD) { 194 fip->fi_readers++; 195 if (fip->fi_readers == 1) { 196 wso->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 sounlock(wso, s); 206 goto bad; 207 } 208 if (fip->fi_writers == 1) { 209 rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED); 210 if (fip->fi_readers > 0) 211 wakeup(&fip->fi_readers); 212 } 213 } 214 sounlock(wso, s); 215 if ((ap->a_mode & O_NONBLOCK) == 0) { 216 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { 217 VOP_UNLOCK(vp); 218 error = tsleep_nsec(&fip->fi_readers, 219 PCATCH | PSOCK, "fifor", INFSLP); 220 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 221 if (error) 222 goto bad; 223 } 224 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { 225 VOP_UNLOCK(vp); 226 error = tsleep_nsec(&fip->fi_writers, 227 PCATCH | PSOCK, "fifow", INFSLP); 228 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 229 if (error) 230 goto bad; 231 } 232 } 233 return (0); 234 bad: 235 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 236 return (error); 237 } 238 239 /* 240 * Vnode op for read 241 */ 242 /* ARGSUSED */ 243 int 244 fifo_read(void *v) 245 { 246 struct vop_read_args *ap = v; 247 struct uio *uio = ap->a_uio; 248 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 249 int error, flags = 0; 250 251 #ifdef DIAGNOSTIC 252 if (uio->uio_rw != UIO_READ) 253 panic("fifo_read mode"); 254 #endif 255 if (uio->uio_resid == 0) 256 return (0); 257 if (ap->a_ioflag & IO_NDELAY) 258 flags |= MSG_DONTWAIT; 259 VOP_UNLOCK(ap->a_vp); 260 error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0); 261 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 262 if (ap->a_ioflag & IO_NDELAY) { 263 if (error == EWOULDBLOCK && 264 ap->a_vp->v_fifoinfo->fi_writers == 0) 265 error = 0; 266 } 267 return (error); 268 } 269 270 /* 271 * Vnode op for write 272 */ 273 /* ARGSUSED */ 274 int 275 fifo_write(void *v) 276 { 277 struct vop_write_args *ap = v; 278 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 279 int error, flags = 0; 280 281 #ifdef DIAGNOSTIC 282 if (ap->a_uio->uio_rw != UIO_WRITE) 283 panic("fifo_write mode"); 284 #endif 285 if (ap->a_ioflag & IO_NDELAY) 286 flags |= MSG_DONTWAIT; 287 VOP_UNLOCK(ap->a_vp); 288 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags); 289 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 290 return (error); 291 } 292 293 /* 294 * Device ioctl operation. 295 */ 296 /* ARGSUSED */ 297 int 298 fifo_ioctl(void *v) 299 { 300 struct vop_ioctl_args *ap = v; 301 struct file filetmp; 302 int error; 303 304 if (ap->a_command == FIONBIO) 305 return (0); 306 if (ap->a_fflag & FREAD) { 307 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 308 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 309 if (error) 310 return (error); 311 } 312 if (ap->a_fflag & FWRITE) { 313 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 314 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 315 if (error) 316 return (error); 317 } 318 return (0); 319 } 320 321 /* ARGSUSED */ 322 int 323 fifo_poll(void *v) 324 { 325 struct vop_poll_args *ap = v; 326 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 327 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 328 int events = 0; 329 int revents = 0; 330 int s; 331 332 /* 333 * FIFOs don't support out-of-band or high priority data. 334 */ 335 s = solock(rso); 336 if (ap->a_fflag & FREAD) 337 events |= ap->a_events & (POLLIN | POLLRDNORM); 338 if (ap->a_fflag & FWRITE) 339 events |= ap->a_events & (POLLOUT | POLLWRNORM); 340 341 if (events & (POLLIN | POLLRDNORM)) { 342 if (soreadable(rso)) 343 revents |= events & (POLLIN | POLLRDNORM); 344 } 345 /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ 346 if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLL_NOHUP)) { 347 revents |= POLLHUP; 348 } else if (events & (POLLOUT | POLLWRNORM)) { 349 if (sowriteable(wso)) 350 revents |= events & (POLLOUT | POLLWRNORM); 351 } 352 if (revents == 0) { 353 /* We want to return POLLHUP even if no valid events set. */ 354 if (events == 0 && !(ap->a_events & POLL_NOHUP)) 355 events = POLLIN; 356 if (events & (POLLIN | POLLRDNORM)) { 357 selrecord(ap->a_p, &rso->so_rcv.sb_sel); 358 rso->so_rcv.sb_flags |= SB_SEL; 359 } 360 if (events & (POLLOUT | POLLWRNORM)) { 361 selrecord(ap->a_p, &wso->so_snd.sb_sel); 362 wso->so_snd.sb_flags |= SB_SEL; 363 } 364 } 365 sounlock(rso, s); 366 return (revents); 367 } 368 369 int 370 fifo_inactive(void *v) 371 { 372 struct vop_inactive_args *ap = v; 373 374 VOP_UNLOCK(ap->a_vp); 375 return (0); 376 } 377 378 379 /* 380 * Device close routine 381 */ 382 /* ARGSUSED */ 383 int 384 fifo_close(void *v) 385 { 386 struct vop_close_args *ap = v; 387 struct vnode *vp = ap->a_vp; 388 struct fifoinfo *fip = vp->v_fifoinfo; 389 int s, error1 = 0, error2 = 0; 390 391 if (fip == NULL) 392 return (0); 393 394 if (ap->a_fflag & FREAD) { 395 if (--fip->fi_readers == 0) { 396 struct socket *wso = fip->fi_writesock; 397 398 s = solock(wso); 399 socantsendmore(wso); 400 sounlock(wso, s); 401 } 402 } 403 if (ap->a_fflag & FWRITE) { 404 if (--fip->fi_writers == 0) { 405 struct socket *rso = fip->fi_readsock; 406 407 s = solock(rso); 408 /* SS_ISDISCONNECTED will result in POLLHUP */ 409 rso->so_state |= SS_ISDISCONNECTED; 410 socantrcvmore(rso); 411 sounlock(rso, s); 412 } 413 } 414 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 415 error1 = soclose(fip->fi_readsock, 0); 416 error2 = soclose(fip->fi_writesock, 0); 417 free(fip, M_VNODE, sizeof *fip); 418 vp->v_fifoinfo = NULL; 419 } 420 return (error1 ? error1 : error2); 421 } 422 423 int 424 fifo_reclaim(void *v) 425 { 426 struct vop_reclaim_args *ap = v; 427 struct vnode *vp = ap->a_vp; 428 struct fifoinfo *fip = vp->v_fifoinfo; 429 430 if (fip == NULL) 431 return (0); 432 433 soclose(fip->fi_readsock, 0); 434 soclose(fip->fi_writesock, 0); 435 free(fip, M_VNODE, sizeof *fip); 436 vp->v_fifoinfo = NULL; 437 438 return (0); 439 } 440 441 /* 442 * Print out the contents of a fifo vnode. 443 */ 444 int 445 fifo_print(void *v) 446 { 447 struct vop_print_args *ap = v; 448 449 printf("tag VT_NON"); 450 fifo_printinfo(ap->a_vp); 451 printf("\n"); 452 return 0; 453 } 454 455 /* 456 * Print out internal contents of a fifo vnode. 457 */ 458 void 459 fifo_printinfo(struct vnode *vp) 460 { 461 struct fifoinfo *fip = vp->v_fifoinfo; 462 463 printf(", fifo with %ld readers and %ld writers", 464 fip->fi_readers, fip->fi_writers); 465 } 466 467 /* 468 * Return POSIX pathconf information applicable to fifo's. 469 */ 470 int 471 fifo_pathconf(void *v) 472 { 473 struct vop_pathconf_args *ap = v; 474 int error = 0; 475 476 switch (ap->a_name) { 477 case _PC_LINK_MAX: 478 *ap->a_retval = LINK_MAX; 479 break; 480 case _PC_CHOWN_RESTRICTED: 481 *ap->a_retval = 1; 482 break; 483 case _PC_TIMESTAMP_RESOLUTION: 484 *ap->a_retval = 1; 485 break; 486 default: 487 error = EINVAL; 488 break; 489 } 490 491 return (error); 492 } 493 494 /* 495 * Fifo failed operation 496 */ 497 /*ARGSUSED*/ 498 int 499 fifo_ebadf(void *v) 500 { 501 502 return (EBADF); 503 } 504 505 /* 506 * Fifo advisory byte-level locks. 507 */ 508 /* ARGSUSED */ 509 int 510 fifo_advlock(void *v) 511 { 512 return (EOPNOTSUPP); 513 } 514 515 int 516 fifo_kqfilter(void *v) 517 { 518 struct vop_kqfilter_args *ap = v; 519 struct fifoinfo *fip = ap->a_vp->v_fifoinfo; 520 struct sockbuf *sb; 521 struct socket *so; 522 523 switch (ap->a_kn->kn_filter) { 524 case EVFILT_READ: 525 if (!(ap->a_fflag & FREAD)) 526 return (EINVAL); 527 ap->a_kn->kn_fop = &fiforead_filtops; 528 so = fip->fi_readsock; 529 sb = &so->so_rcv; 530 break; 531 case EVFILT_WRITE: 532 if (!(ap->a_fflag & FWRITE)) 533 return (EINVAL); 534 ap->a_kn->kn_fop = &fifowrite_filtops; 535 so = fip->fi_writesock; 536 sb = &so->so_snd; 537 break; 538 case EVFILT_EXCEPT: 539 ap->a_kn->kn_fop = &fifoexcept_filtops; 540 so = fip->fi_readsock; 541 sb = &so->so_rcv; 542 break; 543 default: 544 return (EINVAL); 545 } 546 547 ap->a_kn->kn_hook = so; 548 549 klist_insert_locked(&sb->sb_sel.si_note, ap->a_kn); 550 551 return (0); 552 } 553 554 void 555 filt_fifordetach(struct knote *kn) 556 { 557 struct socket *so = (struct socket *)kn->kn_hook; 558 559 klist_remove_locked(&so->so_rcv.sb_sel.si_note, kn); 560 } 561 562 int 563 filt_fiforead_common(struct knote *kn, struct socket *so) 564 { 565 int rv; 566 567 soassertlocked(so); 568 569 kn->kn_data = so->so_rcv.sb_cc; 570 if (so->so_state & SS_CANTRCVMORE) { 571 kn->kn_flags |= EV_EOF; 572 if (kn->kn_flags & __EV_POLL) { 573 if (so->so_state & SS_ISDISCONNECTED) 574 kn->kn_flags |= __EV_HUP; 575 } 576 rv = 1; 577 } else { 578 kn->kn_flags &= ~EV_EOF; 579 rv = (kn->kn_data > 0); 580 } 581 582 return (rv); 583 } 584 585 int 586 filt_fiforead(struct knote *kn, long hint) 587 { 588 struct socket *so = kn->kn_hook; 589 590 return (filt_fiforead_common(kn, so)); 591 } 592 593 int 594 filt_fiforeadmodify(struct kevent *kev, struct knote *kn) 595 { 596 struct socket *so = kn->kn_hook; 597 int rv, s; 598 599 s = solock(so); 600 knote_modify(kev, kn); 601 rv = filt_fiforead_common(kn, so); 602 sounlock(so, s); 603 604 return (rv); 605 } 606 607 int 608 filt_fiforeadprocess(struct knote *kn, struct kevent *kev) 609 { 610 struct socket *so = kn->kn_hook; 611 int rv, s; 612 613 s = solock(so); 614 if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) 615 rv = 1; 616 else 617 rv = filt_fiforead_common(kn, so); 618 if (rv != 0) 619 knote_submit(kn, kev); 620 sounlock(so, s); 621 622 return (rv); 623 } 624 625 void 626 filt_fifowdetach(struct knote *kn) 627 { 628 struct socket *so = (struct socket *)kn->kn_hook; 629 630 klist_remove_locked(&so->so_snd.sb_sel.si_note, kn); 631 } 632 633 int 634 filt_fifowrite_common(struct knote *kn, struct socket *so) 635 { 636 int rv; 637 638 soassertlocked(so); 639 640 kn->kn_data = sbspace(so, &so->so_snd); 641 if (so->so_state & SS_CANTSENDMORE) { 642 kn->kn_flags |= EV_EOF; 643 rv = 1; 644 } else { 645 kn->kn_flags &= ~EV_EOF; 646 rv = (kn->kn_data >= so->so_snd.sb_lowat); 647 } 648 649 return (rv); 650 } 651 652 int 653 filt_fifowrite(struct knote *kn, long hint) 654 { 655 struct socket *so = kn->kn_hook; 656 657 return (filt_fifowrite_common(kn, so)); 658 } 659 660 int 661 filt_fifowritemodify(struct kevent *kev, struct knote *kn) 662 { 663 struct socket *so = kn->kn_hook; 664 int rv, s; 665 666 s = solock(so); 667 knote_modify(kev, kn); 668 rv = filt_fifowrite_common(kn, so); 669 sounlock(so, s); 670 671 return (rv); 672 } 673 674 int 675 filt_fifowriteprocess(struct knote *kn, struct kevent *kev) 676 { 677 struct socket *so = kn->kn_hook; 678 int rv, s; 679 680 s = solock(so); 681 if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) 682 rv = 1; 683 else 684 rv = filt_fifowrite_common(kn, so); 685 if (rv != 0) 686 knote_submit(kn, kev); 687 sounlock(so, s); 688 689 return (rv); 690 } 691 692 int 693 filt_fifoexcept_common(struct knote *kn, struct socket *so) 694 { 695 int rv = 0; 696 697 soassertlocked(so); 698 699 if (so->so_state & SS_CANTRCVMORE) { 700 kn->kn_flags |= EV_EOF; 701 if (kn->kn_flags & __EV_POLL) { 702 if (so->so_state & SS_ISDISCONNECTED) 703 kn->kn_flags |= __EV_HUP; 704 } 705 rv = 1; 706 } 707 708 return (rv); 709 } 710 711 int 712 filt_fifoexcept(struct knote *kn, long hint) 713 { 714 struct socket *so = kn->kn_hook; 715 716 return (filt_fifoexcept_common(kn, so)); 717 } 718 719 int 720 filt_fifoexceptmodify(struct kevent *kev, struct knote *kn) 721 { 722 struct socket *so = kn->kn_hook; 723 int rv, s; 724 725 s = solock(so); 726 knote_modify(kev, kn); 727 rv = filt_fifoexcept_common(kn, so); 728 sounlock(so, s); 729 730 return (rv); 731 } 732 733 int 734 filt_fifoexceptprocess(struct knote *kn, struct kevent *kev) 735 { 736 struct socket *so = kn->kn_hook; 737 int rv, s; 738 739 s = solock(so); 740 if (kev != NULL && (kn->kn_flags & EV_ONESHOT)) 741 rv = 1; 742 else 743 rv = filt_fifoexcept_common(kn, so); 744 if (rv != 0) 745 knote_submit(kn, kev); 746 sounlock(so, s); 747 748 return (rv); 749 } 750