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.8 (Berkeley) 11/05/91 8 */ 9 10 #include "param.h" 11 #include "time.h" 12 #include "namei.h" 13 #include "vnode.h" 14 #include "socket.h" 15 #include "socketvar.h" 16 #include "stat.h" 17 #include "systm.h" 18 #include "ioctl.h" 19 #include "file.h" 20 #include "fifo.h" 21 #include "errno.h" 22 #include "malloc.h" 23 24 /* 25 * This structure is associated with the FIFO vnode and stores 26 * the state associated with the FIFO. 27 */ 28 struct fifoinfo { 29 struct socket *fi_readsock; 30 struct socket *fi_writesock; 31 long fi_readers; 32 long fi_writers; 33 }; 34 35 struct vnodeops fifo_vnodeops = { 36 fifo_lookup, /* lookup */ 37 fifo_create, /* create */ 38 fifo_mknod, /* mknod */ 39 fifo_open, /* open */ 40 fifo_close, /* close */ 41 fifo_access, /* access */ 42 fifo_getattr, /* getattr */ 43 fifo_setattr, /* setattr */ 44 fifo_read, /* read */ 45 fifo_write, /* write */ 46 fifo_ioctl, /* ioctl */ 47 fifo_select, /* select */ 48 fifo_mmap, /* mmap */ 49 fifo_fsync, /* fsync */ 50 fifo_seek, /* seek */ 51 fifo_remove, /* remove */ 52 fifo_link, /* link */ 53 fifo_rename, /* rename */ 54 fifo_mkdir, /* mkdir */ 55 fifo_rmdir, /* rmdir */ 56 fifo_symlink, /* symlink */ 57 fifo_readdir, /* readdir */ 58 fifo_readlink, /* readlink */ 59 fifo_abortop, /* abortop */ 60 fifo_inactive, /* inactive */ 61 fifo_reclaim, /* reclaim */ 62 fifo_lock, /* lock */ 63 fifo_unlock, /* unlock */ 64 fifo_bmap, /* bmap */ 65 fifo_strategy, /* strategy */ 66 fifo_print, /* print */ 67 fifo_islocked, /* islocked */ 68 fifo_advlock, /* advlock */ 69 fifo_blkatoff, /* blkatoff */ 70 fifo_vget, /* vget */ 71 fifo_valloc, /* valloc */ 72 fifo_vfree, /* vfree */ 73 fifo_truncate, /* truncate */ 74 fifo_update, /* update */ 75 fifo_bwrite, /* bwrite */ 76 }; 77 78 /* 79 * Trivial lookup routine that always fails. 80 */ 81 /* ARGSUSED */ 82 fifo_lookup(vp, ndp, p) 83 struct vnode *vp; 84 struct nameidata *ndp; 85 struct proc *p; 86 { 87 88 ndp->ni_dvp = vp; 89 ndp->ni_vp = NULL; 90 return (ENOTDIR); 91 } 92 93 /* 94 * Open called to set up a new instance of a fifo or 95 * to find an active instance of a fifo. 96 */ 97 /* ARGSUSED */ 98 fifo_open(vp, mode, cred, p) 99 register struct vnode *vp; 100 int mode; 101 struct ucred *cred; 102 struct proc *p; 103 { 104 register struct fifoinfo *fip; 105 struct socket *rso, *wso; 106 int error; 107 static char openstr[] = "fifo"; 108 109 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 110 return (EINVAL); 111 if ((fip = vp->v_fifoinfo) == NULL) { 112 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 113 vp->v_fifoinfo = fip; 114 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 115 free(fip, M_VNODE); 116 vp->v_fifoinfo = NULL; 117 return (error); 118 } 119 fip->fi_readsock = rso; 120 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 121 (void)soclose(rso); 122 free(fip, M_VNODE); 123 vp->v_fifoinfo = NULL; 124 return (error); 125 } 126 fip->fi_writesock = wso; 127 if (error = unp_connect2(wso, rso)) { 128 (void)soclose(wso); 129 (void)soclose(rso); 130 free(fip, M_VNODE); 131 vp->v_fifoinfo = NULL; 132 return (error); 133 } 134 wso->so_state |= SS_CANTRCVMORE; 135 rso->so_state |= SS_CANTSENDMORE; 136 } 137 error = 0; 138 if (mode & FREAD) { 139 fip->fi_readers++; 140 if (fip->fi_readers == 1) { 141 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 142 if (fip->fi_writers > 0) 143 wakeup((caddr_t)&fip->fi_writers); 144 } 145 if (mode & O_NONBLOCK) 146 return (0); 147 while (fip->fi_writers == 0) 148 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 149 openstr, 0)) 150 break; 151 } else { 152 fip->fi_writers++; 153 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 154 error = ENXIO; 155 } else { 156 if (fip->fi_writers == 1) { 157 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 158 if (fip->fi_readers > 0) 159 wakeup((caddr_t)&fip->fi_readers); 160 } 161 while (fip->fi_readers == 0) 162 if (error = tsleep((caddr_t)&fip->fi_writers, 163 PSOCK, openstr, 0)) 164 break; 165 } 166 } 167 if (error) 168 fifo_close(vp, mode, cred, p); 169 return (error); 170 } 171 172 /* 173 * Vnode op for read 174 */ 175 /* ARGSUSED */ 176 fifo_read(vp, uio, ioflag, cred) 177 struct vnode *vp; 178 register struct uio *uio; 179 int ioflag; 180 struct ucred *cred; 181 { 182 register struct socket *rso = vp->v_fifoinfo->fi_readsock; 183 int error, startresid; 184 185 #ifdef DIAGNOSTIC 186 if (uio->uio_rw != UIO_READ) 187 panic("fifo_read mode"); 188 #endif 189 if (uio->uio_resid == 0) 190 return (0); 191 if (ioflag & IO_NDELAY) 192 rso->so_state |= SS_NBIO; 193 startresid = uio->uio_resid; 194 VOP_UNLOCK(vp); 195 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 196 (struct mbuf **)0, (struct mbuf **)0); 197 VOP_LOCK(vp); 198 /* 199 * Clear EOF indication after first such return. 200 */ 201 if (uio->uio_resid == startresid) 202 rso->so_state &= ~SS_CANTRCVMORE; 203 if (ioflag & IO_NDELAY) 204 rso->so_state &= ~SS_NBIO; 205 return (error); 206 } 207 208 /* 209 * Vnode op for write 210 */ 211 /* ARGSUSED */ 212 fifo_write(vp, uio, ioflag, cred) 213 struct vnode *vp; 214 register struct uio *uio; 215 int ioflag; 216 struct ucred *cred; 217 { 218 struct socket *wso = vp->v_fifoinfo->fi_writesock; 219 int error; 220 221 #ifdef DIAGNOSTIC 222 if (uio->uio_rw != UIO_WRITE) 223 panic("fifo_write mode"); 224 #endif 225 if (ioflag & IO_NDELAY) 226 wso->so_state |= SS_NBIO; 227 VOP_UNLOCK(vp); 228 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 229 VOP_LOCK(vp); 230 if (ioflag & IO_NDELAY) 231 wso->so_state &= ~SS_NBIO; 232 return (error); 233 } 234 235 /* 236 * Device ioctl operation. 237 */ 238 /* ARGSUSED */ 239 fifo_ioctl(vp, com, data, fflag, cred, p) 240 struct vnode *vp; 241 int com; 242 caddr_t data; 243 int fflag; 244 struct ucred *cred; 245 struct proc *p; 246 { 247 struct file filetmp; 248 int error; 249 250 if (com == FIONBIO) 251 return (0); 252 if (fflag & FREAD) 253 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 254 else 255 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 256 return (soo_ioctl(&filetmp, com, data, p)); 257 } 258 259 /* ARGSUSED */ 260 fifo_select(vp, which, fflag, cred, p) 261 struct vnode *vp; 262 int which, fflag; 263 struct ucred *cred; 264 struct proc *p; 265 { 266 struct file filetmp; 267 int error; 268 269 if (fflag & FREAD) 270 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 271 else 272 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 273 return (soo_select(&filetmp, which, p)); 274 } 275 276 /* 277 * This is a noop, simply returning what one has been given. 278 */ 279 fifo_bmap(vp, bn, vpp, bnp) 280 struct vnode *vp; 281 daddr_t bn; 282 struct vnode **vpp; 283 daddr_t *bnp; 284 { 285 286 if (vpp != NULL) 287 *vpp = vp; 288 if (bnp != NULL) 289 *bnp = bn; 290 return (0); 291 } 292 293 /* 294 * At the moment we do not do any locking. 295 */ 296 /* ARGSUSED */ 297 fifo_lock(vp) 298 struct vnode *vp; 299 { 300 301 return (0); 302 } 303 304 /* ARGSUSED */ 305 fifo_unlock(vp) 306 struct vnode *vp; 307 { 308 309 return (0); 310 } 311 312 /* 313 * Device close routine 314 */ 315 /* ARGSUSED */ 316 fifo_close(vp, fflag, cred, p) 317 register struct vnode *vp; 318 int fflag; 319 struct ucred *cred; 320 struct proc *p; 321 { 322 register struct fifoinfo *fip = vp->v_fifoinfo; 323 int error1, error2; 324 325 if (fflag & FWRITE) { 326 fip->fi_writers--; 327 if (fip->fi_writers == 0) 328 socantrcvmore(fip->fi_readsock); 329 } else { 330 fip->fi_readers--; 331 if (fip->fi_readers == 0) 332 socantsendmore(fip->fi_writesock); 333 } 334 if (vp->v_usecount > 1) 335 return (0); 336 error1 = soclose(fip->fi_readsock); 337 error2 = soclose(fip->fi_writesock); 338 FREE(fip, M_VNODE); 339 vp->v_fifoinfo = NULL; 340 if (error1) 341 return (error1); 342 return (error2); 343 } 344 345 /* 346 * Print out the contents of a fifo vnode. 347 */ 348 fifo_print(vp) 349 struct vnode *vp; 350 { 351 352 printf("tag VT_NON"); 353 fifo_printinfo(vp); 354 printf("\n"); 355 } 356 357 /* 358 * Print out internal contents of a fifo vnode. 359 */ 360 fifo_printinfo(vp) 361 struct vnode *vp; 362 { 363 register struct fifoinfo *fip = vp->v_fifoinfo; 364 365 printf(", fifo with %d readers and %d writers", 366 fip->fi_readers, fip->fi_writers); 367 } 368 369 /* 370 * Fifo failed operation 371 */ 372 fifo_ebadf() 373 { 374 375 return (EBADF); 376 } 377 378 /* 379 * Fifo advisory byte-level locks. 380 */ 381 /* ARGSUSED */ 382 fifo_advlock(vp, id, op, fl, flags) 383 struct vnode *vp; 384 caddr_t id; 385 int op; 386 struct flock *fl; 387 int flags; 388 { 389 390 return (EOPNOTSUPP); 391 } 392 393 /* 394 * Fifo bad operation 395 */ 396 fifo_badop() 397 { 398 399 panic("fifo_badop called"); 400 /* NOTREACHED */ 401 } 402