1 /* $NetBSD: fifo_vnops.c,v 1.65 2008/04/24 15:18:11 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the NetBSD 18 * Foundation, Inc. and its contributors. 19 * 4. Neither the name of The NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /* 37 * Copyright (c) 1990, 1993, 1995 38 * The Regents of the University of California. All rights reserved. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.65 2008/04/24 15:18:11 ad Exp $"); 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/proc.h> 73 #include <sys/time.h> 74 #include <sys/namei.h> 75 #include <sys/vnode.h> 76 #include <sys/socket.h> 77 #include <sys/protosw.h> 78 #include <sys/socketvar.h> 79 #include <sys/stat.h> 80 #include <sys/ioctl.h> 81 #include <sys/file.h> 82 #include <sys/errno.h> 83 #include <sys/kmem.h> 84 #include <sys/un.h> 85 #include <sys/poll.h> 86 #include <sys/event.h> 87 #include <sys/condvar.h> 88 89 #include <miscfs/fifofs/fifo.h> 90 #include <miscfs/genfs/genfs.h> 91 92 /* 93 * This structure is associated with the FIFO vnode and stores 94 * the state associated with the FIFO. 95 */ 96 struct fifoinfo { 97 struct socket *fi_readsock; 98 struct socket *fi_writesock; 99 kcondvar_t fi_rcv; 100 int fi_readers; 101 kcondvar_t fi_wcv; 102 int fi_writers; 103 }; 104 105 int (**fifo_vnodeop_p)(void *); 106 const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 107 { &vop_default_desc, vn_default_error }, 108 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 109 { &vop_create_desc, fifo_create }, /* create */ 110 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 111 { &vop_open_desc, fifo_open }, /* open */ 112 { &vop_close_desc, fifo_close }, /* close */ 113 { &vop_access_desc, fifo_access }, /* access */ 114 { &vop_getattr_desc, fifo_getattr }, /* getattr */ 115 { &vop_setattr_desc, fifo_setattr }, /* setattr */ 116 { &vop_read_desc, fifo_read }, /* read */ 117 { &vop_write_desc, fifo_write }, /* write */ 118 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 119 { &vop_poll_desc, fifo_poll }, /* poll */ 120 { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ 121 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 122 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 123 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 124 { &vop_seek_desc, fifo_seek }, /* seek */ 125 { &vop_remove_desc, fifo_remove }, /* remove */ 126 { &vop_link_desc, fifo_link }, /* link */ 127 { &vop_rename_desc, fifo_rename }, /* rename */ 128 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 129 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 130 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 131 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 132 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 133 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 134 { &vop_inactive_desc, fifo_inactive }, /* inactive */ 135 { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */ 136 { &vop_lock_desc, fifo_lock }, /* lock */ 137 { &vop_unlock_desc, fifo_unlock }, /* unlock */ 138 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 139 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 140 { &vop_print_desc, fifo_print }, /* print */ 141 { &vop_islocked_desc, fifo_islocked }, /* islocked */ 142 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 143 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 144 { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ 145 { &vop_putpages_desc, fifo_putpages }, /* putpages */ 146 { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL } 147 }; 148 const struct vnodeopv_desc fifo_vnodeop_opv_desc = 149 { &fifo_vnodeop_p, fifo_vnodeop_entries }; 150 151 /* 152 * Trivial lookup routine that always fails. 153 */ 154 /* ARGSUSED */ 155 int 156 fifo_lookup(void *v) 157 { 158 struct vop_lookup_args /* { 159 struct vnode *a_dvp; 160 struct vnode **a_vpp; 161 struct componentname *a_cnp; 162 } */ *ap = v; 163 164 *ap->a_vpp = NULL; 165 return (ENOTDIR); 166 } 167 168 /* 169 * Open called to set up a new instance of a fifo or 170 * to find an active instance of a fifo. 171 */ 172 /* ARGSUSED */ 173 int 174 fifo_open(void *v) 175 { 176 struct vop_open_args /* { 177 struct vnode *a_vp; 178 int a_mode; 179 kauth_cred_t a_cred; 180 } */ *ap = v; 181 struct lwp *l = curlwp; 182 struct vnode *vp; 183 struct fifoinfo *fip; 184 struct proc *p; 185 struct socket *rso, *wso; 186 int error; 187 188 vp = ap->a_vp; 189 p = l->l_proc; 190 191 if ((fip = vp->v_fifoinfo) == NULL) { 192 fip = kmem_alloc(sizeof(*fip), KM_SLEEP); 193 vp->v_fifoinfo = fip; 194 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL); 195 if (error != 0) { 196 kmem_free(fip, sizeof(*fip)); 197 vp->v_fifoinfo = NULL; 198 return (error); 199 } 200 fip->fi_readsock = rso; 201 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso); 202 if (error != 0) { 203 (void)soclose(rso); 204 kmem_free(fip, sizeof(*fip)); 205 vp->v_fifoinfo = NULL; 206 return (error); 207 } 208 fip->fi_writesock = wso; 209 solock(wso); 210 if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) { 211 sounlock(wso); 212 (void)soclose(wso); 213 (void)soclose(rso); 214 kmem_free(fip, sizeof(*fip)); 215 vp->v_fifoinfo = NULL; 216 return (error); 217 } 218 fip->fi_readers = 0; 219 fip->fi_writers = 0; 220 wso->so_state |= SS_CANTRCVMORE; 221 rso->so_state |= SS_CANTSENDMORE; 222 cv_init(&fip->fi_rcv, "fiford"); 223 cv_init(&fip->fi_wcv, "fifowr"); 224 } else { 225 wso = fip->fi_writesock; 226 rso = fip->fi_readsock; 227 solock(wso); 228 } 229 230 if (ap->a_mode & FREAD) { 231 if (fip->fi_readers++ == 0) { 232 wso->so_state &= ~SS_CANTSENDMORE; 233 cv_broadcast(&fip->fi_wcv); 234 } 235 } 236 if (ap->a_mode & FWRITE) { 237 if (fip->fi_writers++ == 0) { 238 rso->so_state &= ~SS_CANTRCVMORE; 239 cv_broadcast(&fip->fi_rcv); 240 } 241 } 242 if (ap->a_mode & FREAD) { 243 if (ap->a_mode & O_NONBLOCK) { 244 } else { 245 while (!soreadable(rso) && fip->fi_writers == 0) { 246 VOP_UNLOCK(vp, 0); 247 error = cv_wait_sig(&fip->fi_rcv, 248 wso->so_lock); 249 sounlock(wso); 250 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 251 if (error) 252 goto bad; 253 solock(wso); 254 } 255 } 256 } 257 if (ap->a_mode & FWRITE) { 258 if (ap->a_mode & O_NONBLOCK) { 259 if (fip->fi_readers == 0) { 260 error = ENXIO; 261 sounlock(wso); 262 goto bad; 263 } 264 } else { 265 while (fip->fi_readers == 0) { 266 VOP_UNLOCK(vp, 0); 267 error = cv_wait_sig(&fip->fi_wcv, 268 wso->so_lock); 269 sounlock(wso); 270 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 271 if (error) 272 goto bad; 273 solock(wso); 274 } 275 } 276 } 277 sounlock(wso); 278 return (0); 279 bad: 280 VOP_CLOSE(vp, ap->a_mode, ap->a_cred); 281 return (error); 282 } 283 284 /* 285 * Vnode op for read 286 */ 287 /* ARGSUSED */ 288 int 289 fifo_read(void *v) 290 { 291 struct vop_read_args /* { 292 struct vnode *a_vp; 293 struct uio *a_uio; 294 int a_ioflag; 295 kauth_cred_t a_cred; 296 } */ *ap = v; 297 struct uio *uio; 298 struct socket *rso; 299 int error; 300 size_t startresid; 301 302 uio = ap->a_uio; 303 rso = ap->a_vp->v_fifoinfo->fi_readsock; 304 #ifdef DIAGNOSTIC 305 if (uio->uio_rw != UIO_READ) 306 panic("fifo_read mode"); 307 #endif 308 if (uio->uio_resid == 0) 309 return (0); 310 startresid = uio->uio_resid; 311 VOP_UNLOCK(ap->a_vp, 0); 312 if (ap->a_ioflag & IO_NDELAY) { 313 /* XXX Bogus, affects other threads. */ 314 rso->so_nbio = 1; 315 } 316 error = (*rso->so_receive)(rso, NULL, uio, NULL, NULL, NULL); 317 /* 318 * Clear EOF indication after first such return. 319 */ 320 if (uio->uio_resid == startresid) 321 rso->so_state &= ~SS_CANTRCVMORE; 322 if (ap->a_ioflag & IO_NDELAY) { 323 rso->so_nbio = 0; 324 if (error == EWOULDBLOCK && 325 ap->a_vp->v_fifoinfo->fi_writers == 0) 326 error = 0; 327 } 328 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 329 return (error); 330 } 331 332 /* 333 * Vnode op for write 334 */ 335 /* ARGSUSED */ 336 int 337 fifo_write(void *v) 338 { 339 struct vop_write_args /* { 340 struct vnode *a_vp; 341 struct uio *a_uio; 342 int a_ioflag; 343 kauth_cred_t a_cred; 344 } */ *ap = v; 345 struct socket *wso; 346 int error; 347 348 wso = ap->a_vp->v_fifoinfo->fi_writesock; 349 #ifdef DIAGNOSTIC 350 if (ap->a_uio->uio_rw != UIO_WRITE) 351 panic("fifo_write mode"); 352 #endif 353 VOP_UNLOCK(ap->a_vp, 0); 354 if (ap->a_ioflag & IO_NDELAY) { 355 /* XXX Bogus, affects other threads. */ 356 wso->so_nbio = 1; 357 } 358 error = (*wso->so_send)(wso, NULL, ap->a_uio, 0, NULL, 0, curlwp); 359 if (ap->a_ioflag & IO_NDELAY) 360 wso->so_nbio = 0; 361 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 362 return (error); 363 } 364 365 /* 366 * Device ioctl operation. 367 */ 368 /* ARGSUSED */ 369 int 370 fifo_ioctl(void *v) 371 { 372 struct vop_ioctl_args /* { 373 struct vnode *a_vp; 374 u_long a_command; 375 void *a_data; 376 int a_fflag; 377 kauth_cred_t a_cred; 378 struct lwp *a_l; 379 } */ *ap = v; 380 struct file filetmp; 381 int error; 382 383 if (ap->a_command == FIONBIO) 384 return (0); 385 if (ap->a_fflag & FREAD) { 386 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 387 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data); 388 if (error) 389 return (error); 390 } 391 if (ap->a_fflag & FWRITE) { 392 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 393 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data); 394 if (error) 395 return (error); 396 } 397 return (0); 398 } 399 400 /* ARGSUSED */ 401 int 402 fifo_poll(void *v) 403 { 404 struct vop_poll_args /* { 405 struct vnode *a_vp; 406 int a_events; 407 struct lwp *a_l; 408 } */ *ap = v; 409 struct socket *so; 410 int revents; 411 412 revents = 0; 413 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { 414 so = ap->a_vp->v_fifoinfo->fi_readsock; 415 if (so) 416 revents |= sopoll(so, ap->a_events); 417 } 418 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { 419 so = ap->a_vp->v_fifoinfo->fi_writesock; 420 if (so) 421 revents |= sopoll(so, ap->a_events); 422 } 423 424 return (revents); 425 } 426 427 int 428 fifo_inactive(void *v) 429 { 430 struct vop_inactive_args /* { 431 struct vnode *a_vp; 432 struct lwp *a_l; 433 } */ *ap = v; 434 435 VOP_UNLOCK(ap->a_vp, 0); 436 return (0); 437 } 438 439 /* 440 * This is a noop, simply returning what one has been given. 441 */ 442 int 443 fifo_bmap(void *v) 444 { 445 struct vop_bmap_args /* { 446 struct vnode *a_vp; 447 daddr_t a_bn; 448 struct vnode **a_vpp; 449 daddr_t *a_bnp; 450 int *a_runp; 451 } */ *ap = v; 452 453 if (ap->a_vpp != NULL) 454 *ap->a_vpp = ap->a_vp; 455 if (ap->a_bnp != NULL) 456 *ap->a_bnp = ap->a_bn; 457 if (ap->a_runp != NULL) 458 *ap->a_runp = 0; 459 return (0); 460 } 461 462 /* 463 * Device close routine 464 */ 465 /* ARGSUSED */ 466 int 467 fifo_close(void *v) 468 { 469 struct vop_close_args /* { 470 struct vnode *a_vp; 471 int a_fflag; 472 kauth_cred_t a_cred; 473 struct lwp *a_l; 474 } */ *ap = v; 475 struct vnode *vp; 476 struct fifoinfo *fip; 477 struct socket *wso, *rso; 478 int isrevoke; 479 480 vp = ap->a_vp; 481 fip = vp->v_fifoinfo; 482 isrevoke = (ap->a_fflag & (FREAD | FWRITE | FNONBLOCK)) == FNONBLOCK; 483 wso = fip->fi_writesock; 484 rso = fip->fi_readsock; 485 solock(wso); 486 if (isrevoke) { 487 if (fip->fi_readers != 0) { 488 fip->fi_readers = 0; 489 socantsendmore(wso); 490 } 491 if (fip->fi_writers != 0) { 492 fip->fi_writers = 0; 493 socantrcvmore(rso); 494 } 495 } else { 496 if ((ap->a_fflag & FREAD) && --fip->fi_readers == 0) 497 socantsendmore(wso); 498 if ((ap->a_fflag & FWRITE) && --fip->fi_writers == 0) 499 socantrcvmore(rso); 500 } 501 if ((fip->fi_readers + fip->fi_writers) == 0) { 502 sounlock(wso); 503 (void) soclose(rso); 504 (void) soclose(wso); 505 cv_destroy(&fip->fi_rcv); 506 cv_destroy(&fip->fi_wcv); 507 kmem_free(fip, sizeof(*fip)); 508 vp->v_fifoinfo = NULL; 509 } else 510 sounlock(wso); 511 return (0); 512 } 513 514 /* 515 * Print out the contents of a fifo vnode. 516 */ 517 int 518 fifo_print(void *v) 519 { 520 struct vop_print_args /* { 521 struct vnode *a_vp; 522 } */ *ap = v; 523 524 printf("tag VT_NON"); 525 fifo_printinfo(ap->a_vp); 526 printf("\n"); 527 return 0; 528 } 529 530 /* 531 * Print out internal contents of a fifo vnode. 532 */ 533 void 534 fifo_printinfo(struct vnode *vp) 535 { 536 struct fifoinfo *fip; 537 538 fip = vp->v_fifoinfo; 539 printf(", fifo with %d readers and %d writers", 540 fip->fi_readers, fip->fi_writers); 541 } 542 543 /* 544 * Return POSIX pathconf information applicable to fifo's. 545 */ 546 int 547 fifo_pathconf(void *v) 548 { 549 struct vop_pathconf_args /* { 550 struct vnode *a_vp; 551 int a_name; 552 register_t *a_retval; 553 } */ *ap = v; 554 555 switch (ap->a_name) { 556 case _PC_LINK_MAX: 557 *ap->a_retval = LINK_MAX; 558 return (0); 559 case _PC_PIPE_BUF: 560 *ap->a_retval = PIPE_BUF; 561 return (0); 562 case _PC_CHOWN_RESTRICTED: 563 *ap->a_retval = 1; 564 return (0); 565 case _PC_SYNC_IO: 566 *ap->a_retval = 1; 567 return (0); 568 default: 569 return (EINVAL); 570 } 571 /* NOTREACHED */ 572 } 573 574 static void 575 filt_fifordetach(struct knote *kn) 576 { 577 struct socket *so; 578 579 so = (struct socket *)kn->kn_hook; 580 solock(so); 581 SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext); 582 if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist)) 583 so->so_rcv.sb_flags &= ~SB_KNOTE; 584 sounlock(so); 585 } 586 587 static int 588 filt_fiforead(struct knote *kn, long hint) 589 { 590 struct socket *so; 591 int rv; 592 593 so = (struct socket *)kn->kn_hook; 594 if (hint != NOTE_SUBMIT) 595 solock(so); 596 kn->kn_data = so->so_rcv.sb_cc; 597 if (so->so_state & SS_CANTRCVMORE) { 598 kn->kn_flags |= EV_EOF; 599 rv = 1; 600 } else { 601 kn->kn_flags &= ~EV_EOF; 602 rv = (kn->kn_data > 0); 603 } 604 if (hint != NOTE_SUBMIT) 605 sounlock(so); 606 return rv; 607 } 608 609 static void 610 filt_fifowdetach(struct knote *kn) 611 { 612 struct socket *so; 613 614 so = (struct socket *)kn->kn_hook; 615 solock(so); 616 SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext); 617 if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist)) 618 so->so_snd.sb_flags &= ~SB_KNOTE; 619 sounlock(so); 620 } 621 622 static int 623 filt_fifowrite(struct knote *kn, long hint) 624 { 625 struct socket *so; 626 int rv; 627 628 so = (struct socket *)kn->kn_hook; 629 if (hint != NOTE_SUBMIT) 630 solock(so); 631 kn->kn_data = sbspace(&so->so_snd); 632 if (so->so_state & SS_CANTSENDMORE) { 633 kn->kn_flags |= EV_EOF; 634 rv = 1; 635 } else { 636 kn->kn_flags &= ~EV_EOF; 637 rv = (kn->kn_data >= so->so_snd.sb_lowat); 638 } 639 if (hint != NOTE_SUBMIT) 640 sounlock(so); 641 return rv; 642 } 643 644 static const struct filterops fiforead_filtops = 645 { 1, NULL, filt_fifordetach, filt_fiforead }; 646 static const struct filterops fifowrite_filtops = 647 { 1, NULL, filt_fifowdetach, filt_fifowrite }; 648 649 /* ARGSUSED */ 650 int 651 fifo_kqfilter(void *v) 652 { 653 struct vop_kqfilter_args /* { 654 struct vnode *a_vp; 655 struct knote *a_kn; 656 } */ *ap = v; 657 struct socket *so; 658 struct sockbuf *sb; 659 660 so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; 661 switch (ap->a_kn->kn_filter) { 662 case EVFILT_READ: 663 ap->a_kn->kn_fop = &fiforead_filtops; 664 sb = &so->so_rcv; 665 break; 666 case EVFILT_WRITE: 667 ap->a_kn->kn_fop = &fifowrite_filtops; 668 sb = &so->so_snd; 669 break; 670 default: 671 return (EINVAL); 672 } 673 674 ap->a_kn->kn_hook = so; 675 676 solock(so); 677 SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, ap->a_kn, kn_selnext); 678 sb->sb_flags |= SB_KNOTE; 679 sounlock(so); 680 681 return (0); 682 } 683