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