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