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