1 /* $OpenBSD: fifo_vnops.c,v 1.96 2022/07/01 09:56:17 mvs 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/unistd.h> 52 53 #include <miscfs/fifofs/fifo.h> 54 55 /* 56 * This structure is associated with the FIFO vnode and stores 57 * the state associated with the FIFO. 58 */ 59 struct fifoinfo { 60 struct socket *fi_readsock; 61 struct socket *fi_writesock; 62 long fi_readers; 63 long fi_writers; 64 }; 65 66 const struct vops fifo_vops = { 67 .vop_lookup = vop_generic_lookup, 68 .vop_create = vop_generic_badop, 69 .vop_mknod = vop_generic_badop, 70 .vop_open = fifo_open, 71 .vop_close = fifo_close, 72 .vop_access = fifo_ebadf, 73 .vop_getattr = fifo_ebadf, 74 .vop_setattr = fifo_ebadf, 75 .vop_read = fifo_read, 76 .vop_write = fifo_write, 77 .vop_ioctl = fifo_ioctl, 78 .vop_kqfilter = fifo_kqfilter, 79 .vop_revoke = vop_generic_revoke, 80 .vop_fsync = nullop, 81 .vop_remove = vop_generic_badop, 82 .vop_link = vop_generic_badop, 83 .vop_rename = vop_generic_badop, 84 .vop_mkdir = vop_generic_badop, 85 .vop_rmdir = vop_generic_badop, 86 .vop_symlink = vop_generic_badop, 87 .vop_readdir = vop_generic_badop, 88 .vop_readlink = vop_generic_badop, 89 .vop_abortop = vop_generic_badop, 90 .vop_inactive = fifo_inactive, 91 .vop_reclaim = fifo_reclaim, 92 .vop_lock = nullop, 93 .vop_unlock = nullop, 94 .vop_islocked = nullop, 95 .vop_bmap = vop_generic_bmap, 96 .vop_strategy = vop_generic_badop, 97 .vop_print = fifo_print, 98 .vop_pathconf = fifo_pathconf, 99 .vop_advlock = fifo_advlock, 100 .vop_bwrite = nullop 101 }; 102 103 void filt_fifordetach(struct knote *kn); 104 int filt_fiforead(struct knote *kn, long hint); 105 void filt_fifowdetach(struct knote *kn); 106 int filt_fifowrite(struct knote *kn, long hint); 107 int filt_fifoexcept(struct knote *kn, long hint); 108 int filt_fifomodify(struct kevent *kev, struct knote *kn); 109 int filt_fifoprocess(struct knote *kn, struct kevent *kev); 110 111 const struct filterops fiforead_filtops = { 112 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 113 .f_attach = NULL, 114 .f_detach = filt_fifordetach, 115 .f_event = filt_fiforead, 116 .f_modify = filt_fifomodify, 117 .f_process = filt_fifoprocess, 118 }; 119 120 const struct filterops fifowrite_filtops = { 121 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 122 .f_attach = NULL, 123 .f_detach = filt_fifowdetach, 124 .f_event = filt_fifowrite, 125 .f_modify = filt_fifomodify, 126 .f_process = filt_fifoprocess, 127 }; 128 129 const struct filterops fifoexcept_filtops = { 130 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 131 .f_attach = NULL, 132 .f_detach = filt_fifordetach, 133 .f_event = filt_fifoexcept, 134 .f_modify = filt_fifomodify, 135 .f_process = filt_fifoprocess, 136 }; 137 138 /* 139 * Open called to set up a new instance of a fifo or 140 * to find an active instance of a fifo. 141 */ 142 /* ARGSUSED */ 143 int 144 fifo_open(void *v) 145 { 146 struct vop_open_args *ap = v; 147 struct vnode *vp = ap->a_vp; 148 struct fifoinfo *fip; 149 struct socket *rso, *wso; 150 int error; 151 152 if ((fip = vp->v_fifoinfo) == NULL) { 153 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 154 vp->v_fifoinfo = fip; 155 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) { 156 free(fip, M_VNODE, sizeof *fip); 157 vp->v_fifoinfo = NULL; 158 return (error); 159 } 160 fip->fi_readsock = rso; 161 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) { 162 (void)soclose(rso, 0); 163 free(fip, M_VNODE, sizeof *fip); 164 vp->v_fifoinfo = NULL; 165 return (error); 166 } 167 fip->fi_writesock = wso; 168 if ((error = soconnect2(wso, rso)) != 0) { 169 (void)soclose(wso, 0); 170 (void)soclose(rso, 0); 171 free(fip, M_VNODE, sizeof *fip); 172 vp->v_fifoinfo = NULL; 173 return (error); 174 } 175 fip->fi_readers = fip->fi_writers = 0; 176 solock(wso); 177 wso->so_state |= SS_CANTSENDMORE; 178 wso->so_snd.sb_lowat = PIPE_BUF; 179 sounlock(wso); 180 } else { 181 rso = fip->fi_readsock; 182 wso = fip->fi_writesock; 183 } 184 if (ap->a_mode & FREAD) { 185 fip->fi_readers++; 186 if (fip->fi_readers == 1) { 187 solock(wso); 188 wso->so_state &= ~SS_CANTSENDMORE; 189 sounlock(wso); 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 goto bad; 199 } 200 if (fip->fi_writers == 1) { 201 solock(rso); 202 rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED); 203 sounlock(rso); 204 if (fip->fi_readers > 0) 205 wakeup(&fip->fi_readers); 206 } 207 } 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 int 315 fifo_inactive(void *v) 316 { 317 struct vop_inactive_args *ap = v; 318 319 VOP_UNLOCK(ap->a_vp); 320 return (0); 321 } 322 323 324 /* 325 * Device close routine 326 */ 327 /* ARGSUSED */ 328 int 329 fifo_close(void *v) 330 { 331 struct vop_close_args *ap = v; 332 struct vnode *vp = ap->a_vp; 333 struct fifoinfo *fip = vp->v_fifoinfo; 334 int error1 = 0, error2 = 0; 335 336 if (fip == NULL) 337 return (0); 338 339 if (ap->a_fflag & FREAD) { 340 if (--fip->fi_readers == 0) { 341 struct socket *wso = fip->fi_writesock; 342 343 solock(wso); 344 socantsendmore(wso); 345 sounlock(wso); 346 } 347 } 348 if (ap->a_fflag & FWRITE) { 349 if (--fip->fi_writers == 0) { 350 struct socket *rso = fip->fi_readsock; 351 352 solock(rso); 353 /* SS_ISDISCONNECTED will result in POLLHUP */ 354 rso->so_state |= SS_ISDISCONNECTED; 355 socantrcvmore(rso); 356 sounlock(rso); 357 } 358 } 359 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 360 error1 = soclose(fip->fi_readsock, 0); 361 error2 = soclose(fip->fi_writesock, 0); 362 free(fip, M_VNODE, sizeof *fip); 363 vp->v_fifoinfo = NULL; 364 } 365 return (error1 ? error1 : error2); 366 } 367 368 int 369 fifo_reclaim(void *v) 370 { 371 struct vop_reclaim_args *ap = v; 372 struct vnode *vp = ap->a_vp; 373 struct fifoinfo *fip = vp->v_fifoinfo; 374 375 if (fip == NULL) 376 return (0); 377 378 soclose(fip->fi_readsock, 0); 379 soclose(fip->fi_writesock, 0); 380 free(fip, M_VNODE, sizeof *fip); 381 vp->v_fifoinfo = NULL; 382 383 return (0); 384 } 385 386 /* 387 * Print out the contents of a fifo vnode. 388 */ 389 int 390 fifo_print(void *v) 391 { 392 struct vop_print_args *ap = v; 393 394 printf("tag VT_NON"); 395 fifo_printinfo(ap->a_vp); 396 printf("\n"); 397 return 0; 398 } 399 400 /* 401 * Print out internal contents of a fifo vnode. 402 */ 403 void 404 fifo_printinfo(struct vnode *vp) 405 { 406 struct fifoinfo *fip = vp->v_fifoinfo; 407 408 printf(", fifo with %ld readers and %ld writers", 409 fip->fi_readers, fip->fi_writers); 410 } 411 412 /* 413 * Return POSIX pathconf information applicable to fifo's. 414 */ 415 int 416 fifo_pathconf(void *v) 417 { 418 struct vop_pathconf_args *ap = v; 419 int error = 0; 420 421 switch (ap->a_name) { 422 case _PC_LINK_MAX: 423 *ap->a_retval = LINK_MAX; 424 break; 425 case _PC_CHOWN_RESTRICTED: 426 *ap->a_retval = 1; 427 break; 428 case _PC_TIMESTAMP_RESOLUTION: 429 *ap->a_retval = 1; 430 break; 431 default: 432 error = EINVAL; 433 break; 434 } 435 436 return (error); 437 } 438 439 /* 440 * Fifo failed operation 441 */ 442 /*ARGSUSED*/ 443 int 444 fifo_ebadf(void *v) 445 { 446 447 return (EBADF); 448 } 449 450 /* 451 * Fifo advisory byte-level locks. 452 */ 453 /* ARGSUSED */ 454 int 455 fifo_advlock(void *v) 456 { 457 return (EOPNOTSUPP); 458 } 459 460 int 461 fifo_kqfilter(void *v) 462 { 463 struct vop_kqfilter_args *ap = v; 464 struct fifoinfo *fip = ap->a_vp->v_fifoinfo; 465 struct sockbuf *sb; 466 struct socket *so; 467 468 switch (ap->a_kn->kn_filter) { 469 case EVFILT_READ: 470 if (!(ap->a_fflag & FREAD)) 471 return (EINVAL); 472 ap->a_kn->kn_fop = &fiforead_filtops; 473 so = fip->fi_readsock; 474 sb = &so->so_rcv; 475 break; 476 case EVFILT_WRITE: 477 if (!(ap->a_fflag & FWRITE)) { 478 /* Tell upper layer to ask for POLLUP only */ 479 if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT)) 480 return (EPERM); 481 return (EINVAL); 482 } 483 ap->a_kn->kn_fop = &fifowrite_filtops; 484 so = fip->fi_writesock; 485 sb = &so->so_snd; 486 break; 487 case EVFILT_EXCEPT: 488 if (ap->a_kn->kn_flags & __EV_SELECT) { 489 /* Prevent triggering exceptfds. */ 490 return (EPERM); 491 } 492 if ((ap->a_kn->kn_flags & __EV_POLL) == 0) { 493 /* Disallow usage through kevent(2). */ 494 return (EINVAL); 495 } 496 ap->a_kn->kn_fop = &fifoexcept_filtops; 497 so = fip->fi_readsock; 498 sb = &so->so_rcv; 499 break; 500 default: 501 return (EINVAL); 502 } 503 504 ap->a_kn->kn_hook = so; 505 506 klist_insert(&sb->sb_sel.si_note, ap->a_kn); 507 508 return (0); 509 } 510 511 void 512 filt_fifordetach(struct knote *kn) 513 { 514 struct socket *so = (struct socket *)kn->kn_hook; 515 516 klist_remove(&so->so_rcv.sb_sel.si_note, kn); 517 } 518 519 int 520 filt_fiforead(struct knote *kn, long hint) 521 { 522 struct socket *so = kn->kn_hook; 523 int rv; 524 525 soassertlocked(so); 526 527 kn->kn_data = so->so_rcv.sb_cc; 528 if (so->so_state & SS_CANTRCVMORE) { 529 kn->kn_flags |= EV_EOF; 530 if (kn->kn_flags & __EV_POLL) { 531 if (so->so_state & SS_ISDISCONNECTED) 532 kn->kn_flags |= __EV_HUP; 533 else 534 kn->kn_flags &= ~__EV_HUP; 535 } 536 rv = 1; 537 } else { 538 kn->kn_flags &= ~(EV_EOF | __EV_HUP); 539 rv = (kn->kn_data > 0); 540 } 541 542 return (rv); 543 } 544 545 void 546 filt_fifowdetach(struct knote *kn) 547 { 548 struct socket *so = (struct socket *)kn->kn_hook; 549 550 klist_remove(&so->so_snd.sb_sel.si_note, kn); 551 } 552 553 int 554 filt_fifowrite(struct knote *kn, long hint) 555 { 556 struct socket *so = kn->kn_hook; 557 int rv; 558 559 soassertlocked(so); 560 561 kn->kn_data = sbspace(so, &so->so_snd); 562 if (so->so_state & SS_CANTSENDMORE) { 563 kn->kn_flags |= EV_EOF; 564 rv = 1; 565 } else { 566 kn->kn_flags &= ~EV_EOF; 567 rv = (kn->kn_data >= so->so_snd.sb_lowat); 568 } 569 570 return (rv); 571 } 572 573 int 574 filt_fifoexcept(struct knote *kn, long hint) 575 { 576 struct socket *so = kn->kn_hook; 577 int rv = 0; 578 579 soassertlocked(so); 580 581 if (kn->kn_flags & __EV_POLL) { 582 if (so->so_state & SS_ISDISCONNECTED) { 583 kn->kn_flags |= __EV_HUP; 584 rv = 1; 585 } else { 586 kn->kn_flags &= ~__EV_HUP; 587 } 588 } 589 590 return (rv); 591 } 592 593 int 594 filt_fifomodify(struct kevent *kev, struct knote *kn) 595 { 596 struct socket *so = kn->kn_hook; 597 int rv; 598 599 solock(so); 600 rv = knote_modify(kev, kn); 601 sounlock(so); 602 603 return (rv); 604 } 605 606 int 607 filt_fifoprocess(struct knote *kn, struct kevent *kev) 608 { 609 struct socket *so = kn->kn_hook; 610 int rv; 611 612 solock(so); 613 rv = knote_process(kn, kev); 614 sounlock(so); 615 616 return (rv); 617 } 618