1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)fifo_vnops.c 7.13 (Berkeley) 05/14/92 8 */ 9 10 #include "param.h" 11 #include "proc.h" 12 #include "time.h" 13 #include "namei.h" 14 #include "vnode.h" 15 #include "socket.h" 16 #include "socketvar.h" 17 #include "stat.h" 18 #include "systm.h" 19 #include "ioctl.h" 20 #include "file.h" 21 #include "fifo.h" 22 #include "errno.h" 23 #include "malloc.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_ioctl_desc, fifo_ioctl }, /* ioctl */ 50 { &vop_select_desc, fifo_select }, /* select */ 51 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 52 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 53 { &vop_seek_desc, fifo_seek }, /* seek */ 54 { &vop_remove_desc, fifo_remove }, /* remove */ 55 { &vop_link_desc, fifo_link }, /* link */ 56 { &vop_rename_desc, fifo_rename }, /* rename */ 57 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 58 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 59 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 60 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 61 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 62 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 63 { &vop_inactive_desc, fifo_inactive }, /* inactive */ 64 { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */ 65 { &vop_lock_desc, fifo_lock }, /* lock */ 66 { &vop_unlock_desc, fifo_unlock }, /* unlock */ 67 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 68 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 69 { &vop_print_desc, fifo_print }, /* print */ 70 { &vop_islocked_desc, fifo_islocked }, /* islocked */ 71 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 72 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 73 { &vop_vget_desc, fifo_vget }, /* vget */ 74 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 75 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 76 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 77 { &vop_update_desc, fifo_update }, /* update */ 78 { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ 79 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 80 }; 81 struct vnodeopv_desc fifo_vnodeop_opv_desc = 82 { &fifo_vnodeop_p, fifo_vnodeop_entries }; 83 84 /* 85 * Trivial lookup routine that always fails. 86 */ 87 /* ARGSUSED */ 88 fifo_lookup (ap) 89 struct vop_lookup_args *ap; 90 #define dvp (ap->a_dvp) 91 #define vpp (ap->a_vpp) 92 #define cnp (ap->a_cnp) 93 { 94 95 *vpp = NULL; 96 return (ENOTDIR); 97 } 98 #undef dvp 99 #undef vpp 100 #undef cnp 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 *ap; 109 #define vp (ap->a_vp) 110 #define mode (ap->a_mode) 111 #define cred (ap->a_cred) 112 #define p (ap->a_p) 113 { 114 USES_VOP_CLOSE; 115 USES_VOP_LOCK; 116 USES_VOP_UNLOCK; 117 register struct fifoinfo *fip; 118 struct socket *rso, *wso; 119 int error; 120 static char openstr[] = "fifo"; 121 122 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 123 return (EINVAL); 124 if ((fip = vp->v_fifoinfo) == NULL) { 125 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 126 vp->v_fifoinfo = fip; 127 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 128 free(fip, M_VNODE); 129 vp->v_fifoinfo = NULL; 130 return (error); 131 } 132 fip->fi_readsock = rso; 133 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 134 (void)soclose(rso); 135 free(fip, M_VNODE); 136 vp->v_fifoinfo = NULL; 137 return (error); 138 } 139 fip->fi_writesock = wso; 140 if (error = unp_connect2(wso, rso)) { 141 (void)soclose(wso); 142 (void)soclose(rso); 143 free(fip, M_VNODE); 144 vp->v_fifoinfo = NULL; 145 return (error); 146 } 147 fip->fi_readers = fip->fi_writers = 0; 148 wso->so_state |= SS_CANTRCVMORE; 149 rso->so_state |= SS_CANTSENDMORE; 150 } 151 error = 0; 152 if (mode & FREAD) { 153 fip->fi_readers++; 154 if (fip->fi_readers == 1) { 155 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 156 if (fip->fi_writers > 0) 157 wakeup((caddr_t)&fip->fi_writers); 158 } 159 if (mode & O_NONBLOCK) 160 return (0); 161 while (fip->fi_writers == 0) { 162 VOP_UNLOCK(vp); 163 error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 164 openstr, 0); 165 VOP_LOCK(vp); 166 if (error) 167 break; 168 } 169 } else { 170 fip->fi_writers++; 171 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 172 error = ENXIO; 173 } else { 174 if (fip->fi_writers == 1) { 175 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 176 if (fip->fi_readers > 0) 177 wakeup((caddr_t)&fip->fi_readers); 178 } 179 while (fip->fi_readers == 0) { 180 VOP_UNLOCK(vp); 181 error = tsleep((caddr_t)&fip->fi_writers, 182 PSOCK, openstr, 0); 183 VOP_LOCK(vp); 184 if (error) 185 break; 186 } 187 } 188 } 189 if (error) 190 VOP_CLOSE(vp, mode, cred, p); 191 return (error); 192 } 193 #undef vp 194 #undef mode 195 #undef cred 196 #undef p 197 198 /* 199 * Vnode op for read 200 */ 201 /* ARGSUSED */ 202 fifo_read (ap) 203 struct vop_read_args *ap; 204 #define vp (ap->a_vp) 205 #define uio (ap->a_uio) 206 #define ioflag (ap->a_ioflag) 207 #define cred (ap->a_cred) 208 { 209 USES_VOP_LOCK; 210 USES_VOP_UNLOCK; 211 register struct socket *rso = vp->v_fifoinfo->fi_readsock; 212 int error, startresid; 213 214 #ifdef DIAGNOSTIC 215 if (uio->uio_rw != UIO_READ) 216 panic("fifo_read mode"); 217 #endif 218 if (uio->uio_resid == 0) 219 return (0); 220 if (ioflag & IO_NDELAY) 221 rso->so_state |= SS_NBIO; 222 startresid = uio->uio_resid; 223 VOP_UNLOCK(vp); 224 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 225 (struct mbuf **)0, (struct mbuf **)0); 226 VOP_LOCK(vp); 227 /* 228 * Clear EOF indication after first such return. 229 */ 230 if (uio->uio_resid == startresid) 231 rso->so_state &= ~SS_CANTRCVMORE; 232 if (ioflag & IO_NDELAY) 233 rso->so_state &= ~SS_NBIO; 234 return (error); 235 } 236 #undef vp 237 #undef uio 238 #undef ioflag 239 #undef cred 240 241 /* 242 * Vnode op for write 243 */ 244 /* ARGSUSED */ 245 fifo_write (ap) 246 struct vop_write_args *ap; 247 #define vp (ap->a_vp) 248 #define uio (ap->a_uio) 249 #define ioflag (ap->a_ioflag) 250 #define cred (ap->a_cred) 251 { 252 USES_VOP_LOCK; 253 USES_VOP_UNLOCK; 254 struct socket *wso = vp->v_fifoinfo->fi_writesock; 255 int error; 256 257 #ifdef DIAGNOSTIC 258 if (uio->uio_rw != UIO_WRITE) 259 panic("fifo_write mode"); 260 #endif 261 if (ioflag & IO_NDELAY) 262 wso->so_state |= SS_NBIO; 263 VOP_UNLOCK(vp); 264 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0, 0); 265 VOP_LOCK(vp); 266 if (ioflag & IO_NDELAY) 267 wso->so_state &= ~SS_NBIO; 268 return (error); 269 } 270 #undef vp 271 #undef uio 272 #undef ioflag 273 #undef cred 274 275 /* 276 * Device ioctl operation. 277 */ 278 /* ARGSUSED */ 279 fifo_ioctl (ap) 280 struct vop_ioctl_args *ap; 281 #define vp (ap->a_vp) 282 #define com (ap->a_command) 283 #define data (ap->a_data) 284 #define fflag (ap->a_fflag) 285 #define cred (ap->a_cred) 286 #define p (ap->a_p) 287 { 288 struct file filetmp; 289 int error; 290 291 if (com == FIONBIO) 292 return (0); 293 if (fflag & FREAD) 294 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 295 else 296 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 297 return (soo_ioctl(&filetmp, com, data, p)); 298 } 299 #undef vp 300 #undef com 301 #undef data 302 #undef fflag 303 #undef cred 304 #undef p 305 306 /* ARGSUSED */ 307 fifo_select (ap) 308 struct vop_select_args *ap; 309 #define vp (ap->a_vp) 310 #define which (ap->a_which) 311 #define fflag (ap->a_fflags) 312 #define cred (ap->a_cred) 313 #define p (ap->a_p) 314 { 315 struct file filetmp; 316 int error; 317 318 if (fflag & FREAD) 319 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 320 else 321 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 322 return (soo_select(&filetmp, which, p)); 323 } 324 #undef vp 325 #undef which 326 #undef fflag 327 #undef cred 328 #undef p 329 330 /* 331 * This is a noop, simply returning what one has been given. 332 */ 333 fifo_bmap (ap) 334 struct vop_bmap_args *ap; 335 #define vp (ap->a_vp) 336 #define bn (ap->a_bn) 337 #define vpp (ap->a_vpp) 338 #define bnp (ap->a_bnp) 339 { 340 341 if (vpp != NULL) 342 *vpp = vp; 343 if (bnp != NULL) 344 *bnp = bn; 345 return (0); 346 } 347 #undef vp 348 #undef bn 349 #undef vpp 350 #undef bnp 351 352 /* 353 * At the moment we do not do any locking. 354 */ 355 /* ARGSUSED */ 356 fifo_lock (ap) 357 struct vop_lock_args *ap; 358 #define vp (ap->a_vp) 359 { 360 361 return (0); 362 } 363 #undef vp 364 365 /* ARGSUSED */ 366 fifo_unlock (ap) 367 struct vop_unlock_args *ap; 368 #define vp (ap->a_vp) 369 { 370 371 return (0); 372 } 373 #undef vp 374 375 /* 376 * Device close routine 377 */ 378 /* ARGSUSED */ 379 fifo_close (ap) 380 struct vop_close_args *ap; 381 #define vp (ap->a_vp) 382 #define fflag (ap->a_fflag) 383 #define cred (ap->a_cred) 384 #define p (ap->a_p) 385 { 386 register struct fifoinfo *fip = vp->v_fifoinfo; 387 int error1, error2; 388 389 if (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 #undef vp 409 #undef fflag 410 #undef cred 411 #undef p 412 413 /* 414 * Print out the contents of a fifo vnode. 415 */ 416 fifo_print (ap) 417 struct vop_print_args *ap; 418 #define vp (ap->a_vp) 419 { 420 421 printf("tag VT_NON"); 422 fifo_printinfo(vp); 423 printf("\n"); 424 } 425 #undef vp 426 427 /* 428 * Print out internal contents of a fifo vnode. 429 */ 430 fifo_printinfo(vp) 431 struct vnode *vp; 432 { 433 register struct fifoinfo *fip = vp->v_fifoinfo; 434 435 printf(", fifo with %d readers and %d writers", 436 fip->fi_readers, fip->fi_writers); 437 } 438 439 /* 440 * Fifo failed operation 441 */ 442 fifo_ebadf() 443 { 444 445 return (EBADF); 446 } 447 448 /* 449 * Fifo advisory byte-level locks. 450 */ 451 /* ARGSUSED */ 452 fifo_advlock (ap) 453 struct vop_advlock_args *ap; 454 #define vp (ap->a_vp) 455 #define id (ap->a_id) 456 #define op (ap->a_op) 457 #define fl (ap->a_fl) 458 #define flags (ap->a_flags) 459 { 460 461 return (EOPNOTSUPP); 462 } 463 #undef vp 464 #undef id 465 #undef op 466 #undef fl 467 #undef flags 468 469 /* 470 * Fifo bad operation 471 */ 472 fifo_badop() 473 { 474 475 panic("fifo_badop called"); 476 /* NOTREACHED */ 477 } 478