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.15 (Berkeley) 06/04/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 { 91 92 *ap->a_vpp = NULL; 93 return (ENOTDIR); 94 } 95 96 /* 97 * Open called to set up a new instance of a fifo or 98 * to find an active instance of a fifo. 99 */ 100 /* ARGSUSED */ 101 fifo_open (ap) 102 struct vop_open_args *ap; 103 { 104 USES_VOP_CLOSE; 105 USES_VOP_LOCK; 106 USES_VOP_UNLOCK; 107 register struct vnode *vp = ap->a_vp; 108 register struct fifoinfo *fip; 109 struct socket *rso, *wso; 110 int error; 111 static char openstr[] = "fifo"; 112 113 if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 114 return (EINVAL); 115 if ((fip = vp->v_fifoinfo) == NULL) { 116 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 117 vp->v_fifoinfo = fip; 118 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 119 free(fip, M_VNODE); 120 vp->v_fifoinfo = NULL; 121 return (error); 122 } 123 fip->fi_readsock = rso; 124 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 125 (void)soclose(rso); 126 free(fip, M_VNODE); 127 vp->v_fifoinfo = NULL; 128 return (error); 129 } 130 fip->fi_writesock = wso; 131 if (error = unp_connect2(wso, rso)) { 132 (void)soclose(wso); 133 (void)soclose(rso); 134 free(fip, M_VNODE); 135 vp->v_fifoinfo = NULL; 136 return (error); 137 } 138 fip->fi_readers = fip->fi_writers = 0; 139 wso->so_state |= SS_CANTRCVMORE; 140 rso->so_state |= SS_CANTSENDMORE; 141 } 142 error = 0; 143 if (ap->a_mode & FREAD) { 144 fip->fi_readers++; 145 if (fip->fi_readers == 1) { 146 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 147 if (fip->fi_writers > 0) 148 wakeup((caddr_t)&fip->fi_writers); 149 } 150 if (ap->a_mode & O_NONBLOCK) 151 return (0); 152 while (fip->fi_writers == 0) { 153 VOP_UNLOCK(vp); 154 error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 155 openstr, 0); 156 VOP_LOCK(vp); 157 if (error) 158 break; 159 } 160 } else { 161 fip->fi_writers++; 162 if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) { 163 error = ENXIO; 164 } else { 165 if (fip->fi_writers == 1) { 166 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 167 if (fip->fi_readers > 0) 168 wakeup((caddr_t)&fip->fi_readers); 169 } 170 while (fip->fi_readers == 0) { 171 VOP_UNLOCK(vp); 172 error = tsleep((caddr_t)&fip->fi_writers, 173 PSOCK, openstr, 0); 174 VOP_LOCK(vp); 175 if (error) 176 break; 177 } 178 } 179 } 180 if (error) 181 VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p); 182 return (error); 183 } 184 185 /* 186 * Vnode op for read 187 */ 188 /* ARGSUSED */ 189 fifo_read (ap) 190 struct vop_read_args *ap; 191 { 192 USES_VOP_LOCK; 193 USES_VOP_UNLOCK; 194 register struct uio *uio = ap->a_uio; 195 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 196 int error, startresid; 197 198 #ifdef DIAGNOSTIC 199 if (uio->uio_rw != UIO_READ) 200 panic("fifo_read mode"); 201 #endif 202 if (uio->uio_resid == 0) 203 return (0); 204 if (ap->a_ioflag & IO_NDELAY) 205 rso->so_state |= SS_NBIO; 206 startresid = uio->uio_resid; 207 VOP_UNLOCK(ap->a_vp); 208 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 209 (struct mbuf **)0, (struct mbuf **)0); 210 VOP_LOCK(ap->a_vp); 211 /* 212 * Clear EOF indication after first such return. 213 */ 214 if (uio->uio_resid == startresid) 215 rso->so_state &= ~SS_CANTRCVMORE; 216 if (ap->a_ioflag & IO_NDELAY) 217 rso->so_state &= ~SS_NBIO; 218 return (error); 219 } 220 221 /* 222 * Vnode op for write 223 */ 224 /* ARGSUSED */ 225 fifo_write (ap) 226 struct vop_write_args *ap; 227 { 228 USES_VOP_LOCK; 229 USES_VOP_UNLOCK; 230 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 231 int error; 232 233 #ifdef DIAGNOSTIC 234 if (ap->a_uio->uio_rw != UIO_WRITE) 235 panic("fifo_write mode"); 236 #endif 237 if (ap->a_ioflag & IO_NDELAY) 238 wso->so_state |= SS_NBIO; 239 VOP_UNLOCK(ap->a_vp); 240 error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0); 241 VOP_LOCK(ap->a_vp); 242 if (ap->a_ioflag & IO_NDELAY) 243 wso->so_state &= ~SS_NBIO; 244 return (error); 245 } 246 247 /* 248 * Device ioctl operation. 249 */ 250 /* ARGSUSED */ 251 fifo_ioctl (ap) 252 struct vop_ioctl_args *ap; 253 { 254 struct file filetmp; 255 int error; 256 257 if (ap->a_command == FIONBIO) 258 return (0); 259 if (ap->a_fflag & FREAD) 260 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 261 else 262 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 263 return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p)); 264 } 265 266 /* ARGSUSED */ 267 fifo_select (ap) 268 struct vop_select_args *ap; 269 { 270 struct file filetmp; 271 int error; 272 273 if (ap->a_fflags & FREAD) 274 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; 275 else 276 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; 277 return (soo_select(&filetmp, ap->a_which, ap->a_p)); 278 } 279 280 /* 281 * This is a noop, simply returning what one has been given. 282 */ 283 fifo_bmap (ap) 284 struct vop_bmap_args *ap; 285 { 286 287 if (ap->a_vpp != NULL) 288 *ap->a_vpp = ap->a_vp; 289 if (ap->a_bnp != NULL) 290 *ap->a_bnp = ap->a_bn; 291 return (0); 292 } 293 294 /* 295 * At the moment we do not do any locking. 296 */ 297 /* ARGSUSED */ 298 fifo_lock (ap) 299 struct vop_lock_args *ap; 300 { 301 302 return (0); 303 } 304 305 /* ARGSUSED */ 306 fifo_unlock (ap) 307 struct vop_unlock_args *ap; 308 { 309 310 return (0); 311 } 312 313 /* 314 * Device close routine 315 */ 316 /* ARGSUSED */ 317 fifo_close (ap) 318 struct vop_close_args *ap; 319 { 320 register struct vnode *vp = ap->a_vp; 321 register struct fifoinfo *fip = vp->v_fifoinfo; 322 int error1, error2; 323 324 if (ap->a_fflag & FWRITE) { 325 fip->fi_writers--; 326 if (fip->fi_writers == 0) 327 socantrcvmore(fip->fi_readsock); 328 } else { 329 fip->fi_readers--; 330 if (fip->fi_readers == 0) 331 socantsendmore(fip->fi_writesock); 332 } 333 if (vp->v_usecount > 1) 334 return (0); 335 error1 = soclose(fip->fi_readsock); 336 error2 = soclose(fip->fi_writesock); 337 FREE(fip, M_VNODE); 338 vp->v_fifoinfo = NULL; 339 if (error1) 340 return (error1); 341 return (error2); 342 } 343 344 /* 345 * Print out the contents of a fifo vnode. 346 */ 347 fifo_print (ap) 348 struct vop_print_args *ap; 349 { 350 351 printf("tag VT_NON"); 352 fifo_printinfo(ap->a_vp); 353 printf("\n"); 354 } 355 356 /* 357 * Print out internal contents of a fifo vnode. 358 */ 359 fifo_printinfo(vp) 360 struct vnode *vp; 361 { 362 register struct fifoinfo *fip = vp->v_fifoinfo; 363 364 printf(", fifo with %d readers and %d writers", 365 fip->fi_readers, fip->fi_writers); 366 } 367 368 /* 369 * Fifo failed operation 370 */ 371 fifo_ebadf() 372 { 373 374 return (EBADF); 375 } 376 377 /* 378 * Fifo advisory byte-level locks. 379 */ 380 /* ARGSUSED */ 381 fifo_advlock (ap) 382 struct vop_advlock_args *ap; 383 { 384 385 return (EOPNOTSUPP); 386 } 387 388 /* 389 * Fifo bad operation 390 */ 391 fifo_badop() 392 { 393 394 panic("fifo_badop called"); 395 /* NOTREACHED */ 396 } 397