1 /* $OpenBSD: fifo_vnops.c,v 1.77 2020/06/15 15:29:40 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 = fifo_badop, 70 .vop_mknod = fifo_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 = fifo_badop, 84 .vop_link = fifo_badop, 85 .vop_rename = fifo_badop, 86 .vop_mkdir = fifo_badop, 87 .vop_rmdir = fifo_badop, 88 .vop_symlink = fifo_badop, 89 .vop_readdir = fifo_badop, 90 .vop_readlink = fifo_badop, 91 .vop_abortop = fifo_badop, 92 .vop_inactive = fifo_inactive, 93 .vop_reclaim = fifo_reclaim, 94 .vop_lock = vop_generic_lock, 95 .vop_unlock = vop_generic_unlock, 96 .vop_bmap = vop_generic_bmap, 97 .vop_strategy = fifo_badop, 98 .vop_print = fifo_print, 99 .vop_islocked = vop_generic_islocked, 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 110 const struct filterops fiforead_filtops = { 111 .f_flags = FILTEROP_ISFD, 112 .f_attach = NULL, 113 .f_detach = filt_fifordetach, 114 .f_event = filt_fiforead, 115 }; 116 117 const struct filterops fifowrite_filtops = { 118 .f_flags = FILTEROP_ISFD, 119 .f_attach = NULL, 120 .f_detach = filt_fifowdetach, 121 .f_event = filt_fifowrite, 122 }; 123 124 /* 125 * Open called to set up a new instance of a fifo or 126 * to find an active instance of a fifo. 127 */ 128 /* ARGSUSED */ 129 int 130 fifo_open(void *v) 131 { 132 struct vop_open_args *ap = v; 133 struct vnode *vp = ap->a_vp; 134 struct fifoinfo *fip; 135 struct socket *rso, *wso; 136 int s, error; 137 138 if ((fip = vp->v_fifoinfo) == NULL) { 139 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 140 vp->v_fifoinfo = fip; 141 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) { 142 free(fip, M_VNODE, sizeof *fip); 143 vp->v_fifoinfo = NULL; 144 return (error); 145 } 146 fip->fi_readsock = rso; 147 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) { 148 (void)soclose(rso, 0); 149 free(fip, M_VNODE, sizeof *fip); 150 vp->v_fifoinfo = NULL; 151 return (error); 152 } 153 fip->fi_writesock = wso; 154 if ((error = soconnect2(wso, rso)) != 0) { 155 (void)soclose(wso, 0); 156 (void)soclose(rso, 0); 157 free(fip, M_VNODE, sizeof *fip); 158 vp->v_fifoinfo = NULL; 159 return (error); 160 } 161 fip->fi_readers = fip->fi_writers = 0; 162 s = solock(wso); 163 wso->so_state |= SS_CANTSENDMORE; 164 wso->so_snd.sb_lowat = PIPE_BUF; 165 } else { 166 rso = fip->fi_readsock; 167 wso = fip->fi_writesock; 168 s = solock(wso); 169 } 170 if (ap->a_mode & FREAD) { 171 fip->fi_readers++; 172 if (fip->fi_readers == 1) { 173 wso->so_state &= ~SS_CANTSENDMORE; 174 if (fip->fi_writers > 0) 175 wakeup(&fip->fi_writers); 176 } 177 } 178 if (ap->a_mode & FWRITE) { 179 fip->fi_writers++; 180 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { 181 error = ENXIO; 182 sounlock(wso, s); 183 goto bad; 184 } 185 if (fip->fi_writers == 1) { 186 rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED); 187 if (fip->fi_readers > 0) 188 wakeup(&fip->fi_readers); 189 } 190 } 191 sounlock(wso, s); 192 if ((ap->a_mode & O_NONBLOCK) == 0) { 193 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { 194 VOP_UNLOCK(vp); 195 error = tsleep_nsec(&fip->fi_readers, 196 PCATCH | PSOCK, "fifor", INFSLP); 197 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 198 if (error) 199 goto bad; 200 } 201 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { 202 VOP_UNLOCK(vp); 203 error = tsleep_nsec(&fip->fi_writers, 204 PCATCH | PSOCK, "fifow", INFSLP); 205 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 206 if (error) 207 goto bad; 208 } 209 } 210 return (0); 211 bad: 212 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 213 return (error); 214 } 215 216 /* 217 * Vnode op for read 218 */ 219 /* ARGSUSED */ 220 int 221 fifo_read(void *v) 222 { 223 struct vop_read_args *ap = v; 224 struct uio *uio = ap->a_uio; 225 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 226 int error, flags = 0; 227 228 #ifdef DIAGNOSTIC 229 if (uio->uio_rw != UIO_READ) 230 panic("fifo_read mode"); 231 #endif 232 if (uio->uio_resid == 0) 233 return (0); 234 if (ap->a_ioflag & IO_NDELAY) 235 flags |= MSG_DONTWAIT; 236 VOP_UNLOCK(ap->a_vp); 237 error = soreceive(rso, NULL, uio, NULL, NULL, &flags, 0); 238 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 239 if (ap->a_ioflag & IO_NDELAY) { 240 if (error == EWOULDBLOCK && 241 ap->a_vp->v_fifoinfo->fi_writers == 0) 242 error = 0; 243 } 244 return (error); 245 } 246 247 /* 248 * Vnode op for write 249 */ 250 /* ARGSUSED */ 251 int 252 fifo_write(void *v) 253 { 254 struct vop_write_args *ap = v; 255 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 256 int error, flags = 0; 257 258 #ifdef DIAGNOSTIC 259 if (ap->a_uio->uio_rw != UIO_WRITE) 260 panic("fifo_write mode"); 261 #endif 262 if (ap->a_ioflag & IO_NDELAY) 263 flags |= MSG_DONTWAIT; 264 VOP_UNLOCK(ap->a_vp); 265 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, flags); 266 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 267 return (error); 268 } 269 270 /* 271 * Device ioctl operation. 272 */ 273 /* ARGSUSED */ 274 int 275 fifo_ioctl(void *v) 276 { 277 struct vop_ioctl_args *ap = v; 278 struct file filetmp; 279 int error; 280 281 if (ap->a_command == FIONBIO) 282 return (0); 283 if (ap->a_fflag & FREAD) { 284 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 285 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 286 if (error) 287 return (error); 288 } 289 if (ap->a_fflag & FWRITE) { 290 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 291 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 292 if (error) 293 return (error); 294 } 295 return (0); 296 } 297 298 /* ARGSUSED */ 299 int 300 fifo_poll(void *v) 301 { 302 struct vop_poll_args *ap = v; 303 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 304 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 305 int events = 0; 306 int revents = 0; 307 int s; 308 309 /* 310 * FIFOs don't support out-of-band or high priority data. 311 */ 312 s = solock(rso); 313 if (ap->a_fflag & FREAD) 314 events |= ap->a_events & (POLLIN | POLLRDNORM); 315 if (ap->a_fflag & FWRITE) 316 events |= ap->a_events & (POLLOUT | POLLWRNORM); 317 318 if (events & (POLLIN | POLLRDNORM)) { 319 if (soreadable(rso)) 320 revents |= events & (POLLIN | POLLRDNORM); 321 } 322 /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */ 323 if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLL_NOHUP)) { 324 revents |= POLLHUP; 325 } else if (events & (POLLOUT | POLLWRNORM)) { 326 if (sowriteable(wso)) 327 revents |= events & (POLLOUT | POLLWRNORM); 328 } 329 if (revents == 0) { 330 /* We want to return POLLHUP even if no valid events set. */ 331 if (events == 0 && !(ap->a_events & POLL_NOHUP)) 332 events = POLLIN; 333 if (events & (POLLIN | POLLRDNORM)) { 334 selrecord(ap->a_p, &rso->so_rcv.sb_sel); 335 rso->so_rcv.sb_flags |= SB_SEL; 336 } 337 if (events & (POLLOUT | POLLWRNORM)) { 338 selrecord(ap->a_p, &wso->so_snd.sb_sel); 339 wso->so_snd.sb_flags |= SB_SEL; 340 } 341 } 342 sounlock(rso, s); 343 return (revents); 344 } 345 346 int 347 fifo_inactive(void *v) 348 { 349 struct vop_inactive_args *ap = v; 350 351 VOP_UNLOCK(ap->a_vp); 352 return (0); 353 } 354 355 356 /* 357 * Device close routine 358 */ 359 /* ARGSUSED */ 360 int 361 fifo_close(void *v) 362 { 363 struct vop_close_args *ap = v; 364 struct vnode *vp = ap->a_vp; 365 struct fifoinfo *fip = vp->v_fifoinfo; 366 int s, error1 = 0, error2 = 0; 367 368 if (fip == NULL) 369 return (0); 370 371 if (ap->a_fflag & FREAD) { 372 if (--fip->fi_readers == 0) { 373 struct socket *wso = fip->fi_writesock; 374 375 s = solock(wso); 376 socantsendmore(wso); 377 sounlock(wso, s); 378 } 379 } 380 if (ap->a_fflag & FWRITE) { 381 if (--fip->fi_writers == 0) { 382 struct socket *rso = fip->fi_readsock; 383 384 s = solock(rso); 385 /* SS_ISDISCONNECTED will result in POLLHUP */ 386 rso->so_state |= SS_ISDISCONNECTED; 387 socantrcvmore(rso); 388 sounlock(rso, s); 389 } 390 } 391 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 392 error1 = soclose(fip->fi_readsock, 0); 393 error2 = soclose(fip->fi_writesock, 0); 394 free(fip, M_VNODE, sizeof *fip); 395 vp->v_fifoinfo = NULL; 396 } 397 return (error1 ? error1 : error2); 398 } 399 400 int 401 fifo_reclaim(void *v) 402 { 403 struct vop_reclaim_args *ap = v; 404 struct vnode *vp = ap->a_vp; 405 struct fifoinfo *fip = vp->v_fifoinfo; 406 407 if (fip == NULL) 408 return (0); 409 410 soclose(fip->fi_readsock, 0); 411 soclose(fip->fi_writesock, 0); 412 free(fip, M_VNODE, sizeof *fip); 413 vp->v_fifoinfo = NULL; 414 415 return (0); 416 } 417 418 /* 419 * Print out the contents of a fifo vnode. 420 */ 421 int 422 fifo_print(void *v) 423 { 424 struct vop_print_args *ap = v; 425 426 printf("tag VT_NON"); 427 fifo_printinfo(ap->a_vp); 428 printf("\n"); 429 return 0; 430 } 431 432 /* 433 * Print out internal contents of a fifo vnode. 434 */ 435 void 436 fifo_printinfo(struct vnode *vp) 437 { 438 struct fifoinfo *fip = vp->v_fifoinfo; 439 440 printf(", fifo with %ld readers and %ld writers", 441 fip->fi_readers, fip->fi_writers); 442 } 443 444 /* 445 * Return POSIX pathconf information applicable to fifo's. 446 */ 447 int 448 fifo_pathconf(void *v) 449 { 450 struct vop_pathconf_args *ap = v; 451 int error = 0; 452 453 switch (ap->a_name) { 454 case _PC_LINK_MAX: 455 *ap->a_retval = LINK_MAX; 456 break; 457 case _PC_CHOWN_RESTRICTED: 458 *ap->a_retval = 1; 459 break; 460 case _PC_TIMESTAMP_RESOLUTION: 461 *ap->a_retval = 1; 462 break; 463 default: 464 error = EINVAL; 465 break; 466 } 467 468 return (error); 469 } 470 471 /* 472 * Fifo failed operation 473 */ 474 /*ARGSUSED*/ 475 int 476 fifo_ebadf(void *v) 477 { 478 479 return (EBADF); 480 } 481 482 /* 483 * Fifo advisory byte-level locks. 484 */ 485 /* ARGSUSED */ 486 int 487 fifo_advlock(void *v) 488 { 489 return (EOPNOTSUPP); 490 } 491 492 /* 493 * Fifo bad operation 494 */ 495 /*ARGSUSED*/ 496 int 497 fifo_badop(void *v) 498 { 499 500 panic("fifo_badop called"); 501 /* NOTREACHED */ 502 return(0); 503 } 504 505 506 int 507 fifo_kqfilter(void *v) 508 { 509 struct vop_kqfilter_args *ap = v; 510 struct fifoinfo *fip = ap->a_vp->v_fifoinfo; 511 struct sockbuf *sb; 512 struct socket *so; 513 514 switch (ap->a_kn->kn_filter) { 515 case EVFILT_READ: 516 if (!(ap->a_fflag & FREAD)) 517 return (EINVAL); 518 ap->a_kn->kn_fop = &fiforead_filtops; 519 so = fip->fi_readsock; 520 sb = &so->so_rcv; 521 break; 522 case EVFILT_WRITE: 523 if (!(ap->a_fflag & FWRITE)) 524 return (EINVAL); 525 ap->a_kn->kn_fop = &fifowrite_filtops; 526 so = fip->fi_writesock; 527 sb = &so->so_snd; 528 break; 529 default: 530 return (EINVAL); 531 } 532 533 ap->a_kn->kn_hook = so; 534 535 klist_insert(&sb->sb_sel.si_note, ap->a_kn); 536 sb->sb_flagsintr |= SB_KNOTE; 537 538 return (0); 539 } 540 541 void 542 filt_fifordetach(struct knote *kn) 543 { 544 struct socket *so = (struct socket *)kn->kn_hook; 545 546 klist_remove(&so->so_rcv.sb_sel.si_note, kn); 547 if (klist_empty(&so->so_rcv.sb_sel.si_note)) 548 so->so_rcv.sb_flagsintr &= ~SB_KNOTE; 549 } 550 551 int 552 filt_fiforead(struct knote *kn, long hint) 553 { 554 struct socket *so = (struct socket *)kn->kn_hook; 555 int s, rv; 556 557 if ((hint & NOTE_SUBMIT) == 0) 558 s = solock(so); 559 kn->kn_data = so->so_rcv.sb_cc; 560 if (so->so_state & SS_CANTRCVMORE) { 561 kn->kn_flags |= EV_EOF; 562 if (kn->kn_flags & __EV_POLL) { 563 if (so->so_state & SS_ISDISCONNECTED) 564 kn->kn_flags |= __EV_HUP; 565 } 566 rv = 1; 567 } else { 568 kn->kn_flags &= ~EV_EOF; 569 rv = (kn->kn_data > 0); 570 } 571 if ((hint & NOTE_SUBMIT) == 0) 572 sounlock(so, s); 573 574 return (rv); 575 } 576 577 void 578 filt_fifowdetach(struct knote *kn) 579 { 580 struct socket *so = (struct socket *)kn->kn_hook; 581 582 klist_remove(&so->so_snd.sb_sel.si_note, kn); 583 if (klist_empty(&so->so_snd.sb_sel.si_note)) 584 so->so_snd.sb_flagsintr &= ~SB_KNOTE; 585 } 586 587 int 588 filt_fifowrite(struct knote *kn, long hint) 589 { 590 struct socket *so = (struct socket *)kn->kn_hook; 591 int s, rv; 592 593 if ((hint & NOTE_SUBMIT) == 0) 594 s = solock(so); 595 kn->kn_data = sbspace(so, &so->so_snd); 596 if (so->so_state & SS_CANTSENDMORE) { 597 kn->kn_flags |= EV_EOF; 598 rv = 1; 599 } else { 600 kn->kn_flags &= ~EV_EOF; 601 rv = (kn->kn_data >= so->so_snd.sb_lowat); 602 } 603 if ((hint & NOTE_SUBMIT) == 0) 604 sounlock(so, s); 605 606 return (rv); 607 } 608