1 /* $OpenBSD: fifo_vnops.c,v 1.31 2009/08/13 15:00:14 jasper 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/proc.h> 37 #include <sys/systm.h> 38 #include <sys/time.h> 39 #include <sys/namei.h> 40 #include <sys/vnode.h> 41 #include <sys/socket.h> 42 #include <sys/socketvar.h> 43 #include <sys/stat.h> 44 #include <sys/ioctl.h> 45 #include <sys/file.h> 46 #include <sys/event.h> 47 #include <sys/errno.h> 48 #include <sys/malloc.h> 49 #include <sys/poll.h> 50 #include <sys/un.h> 51 #include <miscfs/fifofs/fifo.h> 52 53 /* 54 * This structure is associated with the FIFO vnode and stores 55 * the state associated with the FIFO. 56 */ 57 struct fifoinfo { 58 struct socket *fi_readsock; 59 struct socket *fi_writesock; 60 long fi_readers; 61 long fi_writers; 62 }; 63 64 int (**fifo_vnodeop_p)(void *); 65 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 66 { &vop_default_desc, eopnotsupp }, 67 { &vop_lookup_desc, vop_generic_lookup }, 68 { &vop_create_desc, fifo_badop }, 69 { &vop_mknod_desc, fifo_badop }, 70 { &vop_open_desc, fifo_open }, 71 { &vop_close_desc, fifo_close }, 72 { &vop_access_desc, fifo_ebadf }, 73 { &vop_getattr_desc, fifo_ebadf }, 74 { &vop_setattr_desc, fifo_ebadf }, 75 { &vop_read_desc, fifo_read }, 76 { &vop_write_desc, fifo_write }, 77 { &vop_ioctl_desc, fifo_ioctl }, 78 { &vop_poll_desc, fifo_poll }, 79 { &vop_kqfilter_desc, fifo_kqfilter }, 80 { &vop_revoke_desc, vop_generic_revoke }, 81 { &vop_fsync_desc, nullop }, 82 { &vop_remove_desc, fifo_badop }, 83 { &vop_link_desc, fifo_badop }, 84 { &vop_rename_desc, fifo_badop }, 85 { &vop_mkdir_desc, fifo_badop }, 86 { &vop_rmdir_desc, fifo_badop }, 87 { &vop_symlink_desc, fifo_badop }, 88 { &vop_readdir_desc, fifo_badop }, 89 { &vop_readlink_desc, fifo_badop }, 90 { &vop_abortop_desc, fifo_badop }, 91 { &vop_inactive_desc, fifo_inactive }, 92 { &vop_reclaim_desc, fifo_reclaim }, 93 { &vop_lock_desc, vop_generic_lock }, 94 { &vop_unlock_desc, vop_generic_unlock }, 95 { &vop_bmap_desc, vop_generic_bmap }, 96 { &vop_strategy_desc, fifo_badop }, 97 { &vop_print_desc, fifo_print }, 98 { &vop_islocked_desc, vop_generic_islocked }, 99 { &vop_pathconf_desc, fifo_pathconf }, 100 { &vop_advlock_desc, fifo_advlock }, 101 { &vop_bwrite_desc, nullop }, 102 { NULL, NULL } 103 }; 104 105 struct vnodeopv_desc fifo_vnodeop_opv_desc = 106 { &fifo_vnodeop_p, fifo_vnodeop_entries }; 107 108 int 109 fifo_vnoperate(void *v) 110 { 111 struct vop_generic_args *ap = v; 112 113 return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap)); 114 } 115 116 void filt_fifordetach(struct knote *kn); 117 int filt_fiforead(struct knote *kn, long hint); 118 void filt_fifowdetach(struct knote *kn); 119 int filt_fifowrite(struct knote *kn, long hint); 120 121 struct filterops fiforead_filtops = 122 { 1, NULL, filt_fifordetach, filt_fiforead }; 123 struct filterops fifowrite_filtops = 124 { 1, NULL, filt_fifowdetach, filt_fifowrite }; 125 126 /* 127 * Open called to set up a new instance of a fifo or 128 * to find an active instance of a fifo. 129 */ 130 /* ARGSUSED */ 131 int 132 fifo_open(void *v) 133 { 134 struct vop_open_args *ap = v; 135 struct vnode *vp = ap->a_vp; 136 struct fifoinfo *fip; 137 struct proc *p = ap->a_p; 138 struct socket *rso, *wso; 139 int error; 140 141 if ((fip = vp->v_fifoinfo) == NULL) { 142 fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK); 143 vp->v_fifoinfo = fip; 144 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) { 145 free(fip, M_VNODE); 146 vp->v_fifoinfo = NULL; 147 return (error); 148 } 149 fip->fi_readsock = rso; 150 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) { 151 (void)soclose(rso); 152 free(fip, M_VNODE); 153 vp->v_fifoinfo = NULL; 154 return (error); 155 } 156 fip->fi_writesock = wso; 157 if ((error = unp_connect2(wso, rso)) != 0) { 158 (void)soclose(wso); 159 (void)soclose(rso); 160 free(fip, M_VNODE); 161 vp->v_fifoinfo = NULL; 162 return (error); 163 } 164 fip->fi_readers = fip->fi_writers = 0; 165 wso->so_snd.sb_lowat = PIPE_BUF; 166 rso->so_state |= SS_CANTRCVMORE; 167 } 168 if (ap->a_mode & FREAD) { 169 fip->fi_readers++; 170 if (fip->fi_readers == 1) { 171 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 172 if (fip->fi_writers > 0) 173 wakeup(&fip->fi_writers); 174 } 175 } 176 if (ap->a_mode & FWRITE) { 177 fip->fi_writers++; 178 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { 179 error = ENXIO; 180 goto bad; 181 } 182 if (fip->fi_writers == 1) { 183 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 184 if (fip->fi_readers > 0) 185 wakeup(&fip->fi_readers); 186 } 187 } 188 if ((ap->a_mode & O_NONBLOCK) == 0) { 189 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { 190 VOP_UNLOCK(vp, 0, p); 191 error = tsleep(&fip->fi_readers, 192 PCATCH | PSOCK, "fifor", 0); 193 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 194 if (error) 195 goto bad; 196 } 197 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { 198 VOP_UNLOCK(vp, 0, p); 199 error = tsleep(&fip->fi_writers, 200 PCATCH | PSOCK, "fifow", 0); 201 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 202 if (error) 203 goto bad; 204 } 205 } 206 return (0); 207 bad: 208 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 209 return (error); 210 } 211 212 /* 213 * Vnode op for read 214 */ 215 /* ARGSUSED */ 216 int 217 fifo_read(void *v) 218 { 219 struct vop_read_args *ap = v; 220 struct uio *uio = ap->a_uio; 221 struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 222 struct proc *p = uio->uio_procp; 223 int error; 224 225 #ifdef DIAGNOSTIC 226 if (uio->uio_rw != UIO_READ) 227 panic("fifo_read mode"); 228 #endif 229 if (uio->uio_resid == 0) 230 return (0); 231 if (ap->a_ioflag & IO_NDELAY) 232 rso->so_state |= SS_NBIO; 233 VOP_UNLOCK(ap->a_vp, 0, p); 234 error = soreceive(rso, NULL, uio, NULL, NULL, NULL, 0); 235 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 236 if (ap->a_ioflag & IO_NDELAY) { 237 rso->so_state &= ~SS_NBIO; 238 if (error == EWOULDBLOCK && 239 ap->a_vp->v_fifoinfo->fi_writers == 0) 240 error = 0; 241 } 242 return (error); 243 } 244 245 /* 246 * Vnode op for write 247 */ 248 /* ARGSUSED */ 249 int 250 fifo_write(void *v) 251 { 252 struct vop_write_args *ap = v; 253 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 254 struct proc *p = ap->a_uio->uio_procp; 255 int error; 256 257 #ifdef DIAGNOSTIC 258 if (ap->a_uio->uio_rw != UIO_WRITE) 259 panic("fifo_write mode"); 260 #endif 261 if (ap->a_ioflag & IO_NDELAY) 262 wso->so_state |= SS_NBIO; 263 VOP_UNLOCK(ap->a_vp, 0, p); 264 error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0); 265 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); 266 if (ap->a_ioflag & IO_NDELAY) 267 wso->so_state &= ~SS_NBIO; 268 return (error); 269 } 270 271 /* 272 * Device ioctl operation. 273 */ 274 /* ARGSUSED */ 275 int 276 fifo_ioctl(void *v) 277 { 278 struct vop_ioctl_args *ap = v; 279 struct file filetmp; 280 int error; 281 282 if (ap->a_command == FIONBIO) 283 return (0); 284 if (ap->a_fflag & FREAD) { 285 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 286 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 287 if (error) 288 return (error); 289 } 290 if (ap->a_fflag & FWRITE) { 291 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 292 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); 293 if (error) 294 return (error); 295 } 296 return (0); 297 } 298 299 /* ARGSUSED */ 300 int 301 fifo_poll(void *v) 302 { 303 struct vop_poll_args *ap = v; 304 struct file filetmp; 305 short ostate; 306 int revents = 0; 307 308 if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { 309 /* 310 * Socket and FIFO poll(2) semantics differ wrt EOF on read. 311 * Unlike a normal socket, FIFOs don't care whether or not 312 * SS_CANTRCVMORE is set. To get the correct semantics we 313 * must clear SS_CANTRCVMORE from so_state temporarily. 314 */ 315 ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state; 316 if (ap->a_events & (POLLIN | POLLRDNORM)) 317 ap->a_vp->v_fifoinfo->fi_readsock->so_state &= 318 ~SS_CANTRCVMORE; 319 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 320 if (filetmp.f_data) 321 revents |= soo_poll(&filetmp, ap->a_events, ap->a_p); 322 ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate; 323 } 324 if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { 325 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 326 if (filetmp.f_data) 327 revents |= soo_poll(&filetmp, ap->a_events, ap->a_p); 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, 0, 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 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 socantsendmore(fip->fi_writesock); 360 } 361 if (ap->a_fflag & FWRITE) { 362 if (--fip->fi_writers == 0) 363 socantrcvmore(fip->fi_readsock); 364 } 365 if (fip->fi_readers == 0 && fip->fi_writers == 0) { 366 error1 = soclose(fip->fi_readsock); 367 error2 = soclose(fip->fi_writesock); 368 free(fip, M_VNODE); 369 vp->v_fifoinfo = NULL; 370 } 371 return (error1 ? error1 : error2); 372 } 373 374 int 375 fifo_reclaim(void *v) 376 { 377 struct vop_reclaim_args *ap = v; 378 struct vnode *vp = ap->a_vp; 379 struct fifoinfo *fip = vp->v_fifoinfo; 380 381 if (fip == NULL) 382 return (0); 383 384 soclose(fip->fi_readsock); 385 soclose(fip->fi_writesock); 386 free(fip, M_VNODE); 387 vp->v_fifoinfo = NULL; 388 389 return (0); 390 } 391 392 /* 393 * Print out the contents of a fifo vnode. 394 */ 395 int 396 fifo_print(void *v) 397 { 398 struct vop_print_args *ap = v; 399 400 printf("tag VT_NON"); 401 fifo_printinfo(ap->a_vp); 402 printf("\n"); 403 return 0; 404 } 405 406 /* 407 * Print out internal contents of a fifo vnode. 408 */ 409 void 410 fifo_printinfo(struct vnode *vp) 411 { 412 struct fifoinfo *fip = vp->v_fifoinfo; 413 414 printf(", fifo with %ld readers and %ld writers", 415 fip->fi_readers, fip->fi_writers); 416 } 417 418 /* 419 * Return POSIX pathconf information applicable to fifo's. 420 */ 421 int 422 fifo_pathconf(void *v) 423 { 424 struct vop_pathconf_args *ap = v; 425 426 switch (ap->a_name) { 427 case _PC_LINK_MAX: 428 *ap->a_retval = LINK_MAX; 429 return (0); 430 case _PC_PIPE_BUF: 431 *ap->a_retval = PIPE_BUF; 432 return (0); 433 case _PC_CHOWN_RESTRICTED: 434 *ap->a_retval = 1; 435 return (0); 436 default: 437 return (EINVAL); 438 } 439 /* NOTREACHED */ 440 } 441 442 /* 443 * Fifo failed operation 444 */ 445 /*ARGSUSED*/ 446 int 447 fifo_ebadf(void *v) 448 { 449 450 return (EBADF); 451 } 452 453 /* 454 * Fifo advisory byte-level locks. 455 */ 456 /* ARGSUSED */ 457 int 458 fifo_advlock(void *v) 459 { 460 return (EOPNOTSUPP); 461 } 462 463 /* 464 * Fifo bad operation 465 */ 466 /*ARGSUSED*/ 467 int 468 fifo_badop(void *v) 469 { 470 471 panic("fifo_badop called"); 472 /* NOTREACHED */ 473 return(0); 474 } 475 476 477 int 478 fifo_kqfilter(void *v) 479 { 480 struct vop_kqfilter_args *ap = v; 481 struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; 482 struct sockbuf *sb; 483 484 switch (ap->a_kn->kn_filter) { 485 case EVFILT_READ: 486 ap->a_kn->kn_fop = &fiforead_filtops; 487 sb = &so->so_rcv; 488 break; 489 case EVFILT_WRITE: 490 ap->a_kn->kn_fop = &fifowrite_filtops; 491 sb = &so->so_snd; 492 break; 493 default: 494 return (1); 495 } 496 497 ap->a_kn->kn_hook = so; 498 499 SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext); 500 sb->sb_flags |= SB_KNOTE; 501 502 return (0); 503 } 504 505 void 506 filt_fifordetach(struct knote *kn) 507 { 508 struct socket *so = (struct socket *)kn->kn_hook; 509 510 SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); 511 if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) 512 so->so_rcv.sb_flags &= ~SB_KNOTE; 513 } 514 515 int 516 filt_fiforead(struct knote *kn, long hint) 517 { 518 struct socket *so = (struct socket *)kn->kn_hook; 519 520 kn->kn_data = so->so_rcv.sb_cc; 521 if (so->so_state & SS_CANTRCVMORE) { 522 kn->kn_flags |= EV_EOF; 523 return (1); 524 } 525 kn->kn_flags &= ~EV_EOF; 526 return (kn->kn_data > 0); 527 } 528 529 void 530 filt_fifowdetach(struct knote *kn) 531 { 532 struct socket *so = (struct socket *)kn->kn_hook; 533 534 SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); 535 if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) 536 so->so_snd.sb_flags &= ~SB_KNOTE; 537 } 538 539 int 540 filt_fifowrite(struct knote *kn, long hint) 541 { 542 struct socket *so = (struct socket *)kn->kn_hook; 543 544 kn->kn_data = sbspace(&so->so_snd); 545 if (so->so_state & SS_CANTSENDMORE) { 546 kn->kn_flags |= EV_EOF; 547 return (1); 548 } 549 kn->kn_flags &= ~EV_EOF; 550 return (kn->kn_data >= so->so_snd.sb_lowat); 551 } 552