1 /* $NetBSD: fifo_vnops.c,v 1.9 1994/06/29 06:34:24 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94 36 */ 37 38 #include <sys/param.h> 39 #include <sys/proc.h> 40 #include <sys/time.h> 41 #include <sys/namei.h> 42 #include <sys/vnode.h> 43 #include <sys/socket.h> 44 #include <sys/socketvar.h> 45 #include <sys/stat.h> 46 #include <sys/systm.h> 47 #include <sys/ioctl.h> 48 #include <sys/file.h> 49 #include <sys/errno.h> 50 #include <sys/malloc.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)(); 65 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 66 { &vop_default_desc, vn_default_error }, 67 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 68 { &vop_create_desc, fifo_create }, /* create */ 69 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 70 { &vop_open_desc, fifo_open }, /* open */ 71 { &vop_close_desc, fifo_close }, /* close */ 72 { &vop_access_desc, fifo_access }, /* access */ 73 { &vop_getattr_desc, fifo_getattr }, /* getattr */ 74 { &vop_setattr_desc, fifo_setattr }, /* setattr */ 75 { &vop_read_desc, fifo_read }, /* read */ 76 { &vop_write_desc, fifo_write }, /* write */ 77 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 78 { &vop_select_desc, fifo_select }, /* select */ 79 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 80 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 81 { &vop_seek_desc, fifo_seek }, /* seek */ 82 { &vop_remove_desc, fifo_remove }, /* remove */ 83 { &vop_link_desc, fifo_link }, /* link */ 84 { &vop_rename_desc, fifo_rename }, /* rename */ 85 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 86 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 87 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 88 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 89 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 90 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 91 { &vop_inactive_desc, fifo_inactive }, /* inactive */ 92 { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */ 93 { &vop_lock_desc, fifo_lock }, /* lock */ 94 { &vop_unlock_desc, fifo_unlock }, /* unlock */ 95 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 96 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 97 { &vop_print_desc, fifo_print }, /* print */ 98 { &vop_islocked_desc, fifo_islocked }, /* islocked */ 99 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 100 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 101 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 102 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 103 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 104 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 105 { &vop_update_desc, fifo_update }, /* update */ 106 { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ 107 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 108 }; 109 struct vnodeopv_desc fifo_vnodeop_opv_desc = 110 { &fifo_vnodeop_p, fifo_vnodeop_entries }; 111 112 /* 113 * Trivial lookup routine that always fails. 114 */ 115 /* ARGSUSED */ 116 fifo_lookup(ap) 117 struct vop_lookup_args /* { 118 struct vnode * a_dvp; 119 struct vnode ** a_vpp; 120 struct componentname * a_cnp; 121 } */ *ap; 122 { 123 124 *ap->a_vpp = NULL; 125 return (ENOTDIR); 126 } 127 128 /* 129 * Open called to set up a new instance of a fifo or 130 * to find an active instance of a fifo. 131 */ 132 /* ARGSUSED */ 133 fifo_open(ap) 134 struct vop_open_args /* { 135 struct vnode *a_vp; 136 int a_mode; 137 struct ucred *a_cred; 138 struct proc *a_p; 139 } */ *ap; 140 { 141 register struct vnode *vp = ap->a_vp; 142 register struct fifoinfo *fip; 143 struct socket *rso, *wso; 144 int error; 145 static char openstr[] = "fifo"; 146 147 if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 148 return (EINVAL); 149 if ((fip = vp->v_fifoinfo) == NULL) { 150 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 151 vp->v_fifoinfo = fip; 152 if (error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) { 153 free(fip, M_VNODE); 154 vp->v_fifoinfo = NULL; 155 return (error); 156 } 157 fip->fi_readsock = rso; 158 if (error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) { 159 (void)soclose(rso); 160 free(fip, M_VNODE); 161 vp->v_fifoinfo = NULL; 162 return (error); 163 } 164 fip->fi_writesock = wso; 165 if (error = unp_connect2(wso, rso)) { 166 (void)soclose(wso); 167 (void)soclose(rso); 168 free(fip, M_VNODE); 169 vp->v_fifoinfo = NULL; 170 return (error); 171 } 172 fip->fi_readers = fip->fi_writers = 0; 173 wso->so_state |= SS_CANTRCVMORE; 174 rso->so_state |= SS_CANTSENDMORE; 175 } 176 error = 0; 177 if (ap->a_mode & FREAD) { 178 fip->fi_readers++; 179 if (fip->fi_readers == 1) { 180 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 181 if (fip->fi_writers > 0) 182 wakeup((caddr_t)&fip->fi_writers); 183 } 184 if (ap->a_mode & O_NONBLOCK) 185 return (0); 186 while (fip->fi_writers == 0) { 187 VOP_UNLOCK(vp); 188 error = tsleep((caddr_t)&fip->fi_readers, 189 PCATCH | PSOCK, openstr, 0); 190 VOP_LOCK(vp); 191 if (error) 192 break; 193 } 194 } else { 195 fip->fi_writers++; 196 if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) { 197 error = ENXIO; 198 } else { 199 if (fip->fi_writers == 1) { 200 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 201 if (fip->fi_readers > 0) 202 wakeup((caddr_t)&fip->fi_readers); 203 } 204 while (fip->fi_readers == 0) { 205 VOP_UNLOCK(vp); 206 error = tsleep((caddr_t)&fip->fi_writers, 207 PCATCH | PSOCK, openstr, 0); 208 VOP_LOCK(vp); 209 if (error) 210 break; 211 } 212 } 213 } 214 if (error) 215 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 216 return (error); 217 } 218 219 /* 220 * Vnode op for read 221 */ 222 /* ARGSUSED */ 223 fifo_read(ap) 224 struct vop_read_args /* { 225 struct vnode *a_vp; 226 struct uio *a_uio; 227 int a_ioflag; 228 struct ucred *a_cred; 229 } */ *ap; 230 { 231 register struct uio *uio = ap->a_uio; 232 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 233 int error, startresid; 234 235 #ifdef DIAGNOSTIC 236 if (uio->uio_rw != UIO_READ) 237 panic("fifo_read mode"); 238 #endif 239 if (uio->uio_resid == 0) 240 return (0); 241 if (ap->a_ioflag & IO_NDELAY) 242 rso->so_state |= SS_NBIO; 243 startresid = uio->uio_resid; 244 VOP_UNLOCK(ap->a_vp); 245 error = soreceive(rso, (struct mbuf **)0, uio, 246 (struct mbuf **)0, (struct mbuf **)0, (int *)0); 247 VOP_LOCK(ap->a_vp); 248 /* 249 * Clear EOF indication after first such return. 250 */ 251 if (uio->uio_resid == startresid) 252 rso->so_state &= ~SS_CANTRCVMORE; 253 if (ap->a_ioflag & IO_NDELAY) 254 rso->so_state &= ~SS_NBIO; 255 return (error); 256 } 257 258 /* 259 * Vnode op for write 260 */ 261 /* ARGSUSED */ 262 fifo_write(ap) 263 struct vop_write_args /* { 264 struct vnode *a_vp; 265 struct uio *a_uio; 266 int a_ioflag; 267 struct ucred *a_cred; 268 } */ *ap; 269 { 270 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 271 int error; 272 273 #ifdef DIAGNOSTIC 274 if (ap->a_uio->uio_rw != UIO_WRITE) 275 panic("fifo_write mode"); 276 #endif 277 if (ap->a_ioflag & IO_NDELAY) 278 wso->so_state |= SS_NBIO; 279 VOP_UNLOCK(ap->a_vp); 280 error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0); 281 VOP_LOCK(ap->a_vp); 282 if (ap->a_ioflag & IO_NDELAY) 283 wso->so_state &= ~SS_NBIO; 284 return (error); 285 } 286 287 /* 288 * Device ioctl operation. 289 */ 290 /* ARGSUSED */ 291 fifo_ioctl(ap) 292 struct vop_ioctl_args /* { 293 struct vnode *a_vp; 294 int a_command; 295 caddr_t a_data; 296 int a_fflag; 297 struct ucred *a_cred; 298 struct proc *a_p; 299 } */ *ap; 300 { 301 struct file filetmp; 302 303 if (ap->a_command == FIONBIO) 304 return (0); 305 if (ap->a_fflag & FREAD) 306 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 307 else 308 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 309 return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p)); 310 } 311 312 /* ARGSUSED */ 313 fifo_select(ap) 314 struct vop_select_args /* { 315 struct vnode *a_vp; 316 int a_which; 317 int a_fflags; 318 struct ucred *a_cred; 319 struct proc *a_p; 320 } */ *ap; 321 { 322 struct file filetmp; 323 324 if (ap->a_fflags & FREAD) 325 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 326 else 327 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 328 return (soo_select(&filetmp, ap->a_which, ap->a_p)); 329 } 330 331 /* 332 * This is a noop, simply returning what one has been given. 333 */ 334 fifo_bmap(ap) 335 struct vop_bmap_args /* { 336 struct vnode *a_vp; 337 daddr_t a_bn; 338 struct vnode **a_vpp; 339 daddr_t *a_bnp; 340 } */ *ap; 341 { 342 343 if (ap->a_vpp != NULL) 344 *ap->a_vpp = ap->a_vp; 345 if (ap->a_bnp != NULL) 346 *ap->a_bnp = ap->a_bn; 347 return (0); 348 } 349 350 /* 351 * At the moment we do not do any locking. 352 */ 353 /* ARGSUSED */ 354 fifo_lock(ap) 355 struct vop_lock_args /* { 356 struct vnode *a_vp; 357 } */ *ap; 358 { 359 360 return (0); 361 } 362 363 /* ARGSUSED */ 364 fifo_unlock(ap) 365 struct vop_unlock_args /* { 366 struct vnode *a_vp; 367 } */ *ap; 368 { 369 370 return (0); 371 } 372 373 /* 374 * Device close routine 375 */ 376 /* ARGSUSED */ 377 fifo_close(ap) 378 struct vop_close_args /* { 379 struct vnode *a_vp; 380 int a_fflag; 381 struct ucred *a_cred; 382 struct proc *a_p; 383 } */ *ap; 384 { 385 register struct vnode *vp = ap->a_vp; 386 register struct fifoinfo *fip = vp->v_fifoinfo; 387 int error1, error2; 388 389 if (ap->a_fflag & FWRITE) { 390 fip->fi_writers--; 391 if (fip->fi_writers == 0) 392 socantrcvmore(fip->fi_readsock); 393 } else { 394 fip->fi_readers--; 395 if (fip->fi_readers == 0) 396 socantsendmore(fip->fi_writesock); 397 } 398 if (vp->v_usecount > 1) 399 return (0); 400 error1 = soclose(fip->fi_readsock); 401 error2 = soclose(fip->fi_writesock); 402 FREE(fip, M_VNODE); 403 vp->v_fifoinfo = NULL; 404 if (error1) 405 return (error1); 406 return (error2); 407 } 408 409 /* 410 * Print out the contents of a fifo vnode. 411 */ 412 fifo_print(ap) 413 struct vop_print_args /* { 414 struct vnode *a_vp; 415 } */ *ap; 416 { 417 418 printf("tag VT_NON"); 419 fifo_printinfo(ap->a_vp); 420 printf("\n"); 421 } 422 423 /* 424 * Print out internal contents of a fifo vnode. 425 */ 426 fifo_printinfo(vp) 427 struct vnode *vp; 428 { 429 register struct fifoinfo *fip = vp->v_fifoinfo; 430 431 printf(", fifo with %d readers and %d writers", 432 fip->fi_readers, fip->fi_writers); 433 } 434 435 /* 436 * Return POSIX pathconf information applicable to fifo's. 437 */ 438 fifo_pathconf(ap) 439 struct vop_pathconf_args /* { 440 struct vnode *a_vp; 441 int a_name; 442 int *a_retval; 443 } */ *ap; 444 { 445 446 switch (ap->a_name) { 447 case _PC_LINK_MAX: 448 *ap->a_retval = LINK_MAX; 449 return (0); 450 case _PC_PIPE_BUF: 451 *ap->a_retval = PIPE_BUF; 452 return (0); 453 case _PC_CHOWN_RESTRICTED: 454 *ap->a_retval = 1; 455 return (0); 456 default: 457 return (EINVAL); 458 } 459 /* NOTREACHED */ 460 } 461 462 /* 463 * Fifo failed operation 464 */ 465 fifo_ebadf() 466 { 467 468 return (EBADF); 469 } 470 471 /* 472 * Fifo advisory byte-level locks. 473 */ 474 /* ARGSUSED */ 475 fifo_advlock(ap) 476 struct vop_advlock_args /* { 477 struct vnode *a_vp; 478 caddr_t a_id; 479 int a_op; 480 struct flock *a_fl; 481 int a_flags; 482 } */ *ap; 483 { 484 485 return (EOPNOTSUPP); 486 } 487 488 /* 489 * Fifo bad operation 490 */ 491 fifo_badop() 492 { 493 494 panic("fifo_badop called"); 495 /* NOTREACHED */ 496 } 497