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