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.6 (Berkeley) 03/17/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 "errno.h" 21 #include "malloc.h" 22 23 /* 24 * This structure is associated with the FIFO vnode and stores 25 * the state associated with the FIFO. 26 */ 27 struct fifoinfo { 28 struct socket *fi_readsock; 29 struct socket *fi_writesock; 30 long fi_readers; 31 long fi_writers; 32 }; 33 34 int fifo_lookup(), 35 fifo_open(), 36 fifo_read(), 37 fifo_write(), 38 fifo_strategy(), 39 fifo_bmap(), 40 fifo_ioctl(), 41 fifo_select(), 42 fifo_lock(), 43 fifo_unlock(), 44 fifo_close(), 45 fifo_print(), 46 fifo_advlock(), 47 fifo_ebadf(), 48 fifo_badop(), 49 nullop(); 50 51 struct vnodeops fifo_vnodeops = { 52 fifo_lookup, /* lookup */ 53 fifo_badop, /* create */ 54 fifo_badop, /* mknod */ 55 fifo_open, /* open */ 56 fifo_close, /* close */ 57 fifo_ebadf, /* access */ 58 fifo_ebadf, /* getattr */ 59 fifo_ebadf, /* setattr */ 60 fifo_read, /* read */ 61 fifo_write, /* write */ 62 fifo_ioctl, /* ioctl */ 63 fifo_select, /* select */ 64 fifo_badop, /* mmap */ 65 nullop, /* fsync */ 66 fifo_badop, /* seek */ 67 fifo_badop, /* remove */ 68 fifo_badop, /* link */ 69 fifo_badop, /* rename */ 70 fifo_badop, /* mkdir */ 71 fifo_badop, /* rmdir */ 72 fifo_badop, /* symlink */ 73 fifo_badop, /* readdir */ 74 fifo_badop, /* readlink */ 75 fifo_badop, /* abortop */ 76 nullop, /* inactive */ 77 nullop, /* reclaim */ 78 fifo_lock, /* lock */ 79 fifo_unlock, /* unlock */ 80 fifo_bmap, /* bmap */ 81 fifo_badop, /* strategy */ 82 fifo_print, /* print */ 83 nullop, /* islocked */ 84 fifo_advlock, /* advlock */ 85 }; 86 87 /* 88 * Trivial lookup routine that always fails. 89 */ 90 fifo_lookup(vp, ndp) 91 struct vnode *vp; 92 struct nameidata *ndp; 93 { 94 95 ndp->ni_dvp = vp; 96 ndp->ni_vp = NULL; 97 return (ENOTDIR); 98 } 99 100 /* 101 * Open called to set up a new instance of a fifo or 102 * to find an active instance of a fifo. 103 */ 104 /* ARGSUSED */ 105 fifo_open(vp, mode, cred) 106 register struct vnode *vp; 107 int mode; 108 struct ucred *cred; 109 { 110 register struct fifoinfo *fip; 111 struct socket *rso, *wso; 112 int error; 113 static char openstr[] = "fifo"; 114 115 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 116 return (EINVAL); 117 if ((fip = vp->v_fifoinfo) == NULL) { 118 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 119 vp->v_fifoinfo = fip; 120 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 121 free(fip, M_VNODE); 122 vp->v_fifoinfo = NULL; 123 return (error); 124 } 125 fip->fi_readsock = rso; 126 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 127 (void)soclose(rso); 128 free(fip, M_VNODE); 129 vp->v_fifoinfo = NULL; 130 return (error); 131 } 132 fip->fi_writesock = wso; 133 if (error = unp_connect2(wso, rso)) { 134 (void)soclose(wso); 135 (void)soclose(rso); 136 free(fip, M_VNODE); 137 vp->v_fifoinfo = NULL; 138 return (error); 139 } 140 wso->so_state |= SS_CANTRCVMORE; 141 rso->so_state |= SS_CANTSENDMORE; 142 } 143 error = 0; 144 if (mode & FREAD) { 145 fip->fi_readers++; 146 if (fip->fi_readers == 1) { 147 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 148 if (fip->fi_writers > 0) 149 wakeup((caddr_t)&fip->fi_writers); 150 } 151 if (mode & O_NONBLOCK) 152 return (0); 153 while (fip->fi_writers == 0) 154 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 155 openstr, 0)) 156 break; 157 } else { 158 fip->fi_writers++; 159 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 160 error = ENXIO; 161 } else { 162 if (fip->fi_writers == 1) { 163 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 164 if (fip->fi_readers > 0) 165 wakeup((caddr_t)&fip->fi_readers); 166 } 167 while (fip->fi_readers == 0) 168 if (error = tsleep((caddr_t)&fip->fi_writers, 169 PSOCK, openstr, 0)) 170 break; 171 } 172 } 173 if (error) 174 fifo_close(vp, mode, cred); 175 return (error); 176 } 177 178 /* 179 * Vnode op for read 180 */ 181 /* ARGSUSED */ 182 fifo_read(vp, uio, ioflag, cred) 183 struct vnode *vp; 184 register struct uio *uio; 185 int ioflag; 186 struct ucred *cred; 187 { 188 register struct socket *rso = vp->v_fifoinfo->fi_readsock; 189 int error, startresid; 190 191 if (uio->uio_rw != UIO_READ) 192 panic("fifo_read mode"); 193 if (uio->uio_resid == 0) 194 return (0); 195 if (ioflag & IO_NDELAY) 196 rso->so_state |= SS_NBIO; 197 startresid = uio->uio_resid; 198 VOP_UNLOCK(vp); 199 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 200 (struct mbuf **)0, (struct mbuf **)0); 201 VOP_LOCK(vp); 202 /* 203 * Clear EOF indication after first such return. 204 */ 205 if (uio->uio_resid == startresid) 206 rso->so_state &= ~SS_CANTRCVMORE; 207 if (ioflag & IO_NDELAY) 208 rso->so_state &= ~SS_NBIO; 209 return (error); 210 } 211 212 /* 213 * Vnode op for write 214 */ 215 /* ARGSUSED */ 216 fifo_write(vp, uio, ioflag, cred) 217 struct vnode *vp; 218 register struct uio *uio; 219 int ioflag; 220 struct ucred *cred; 221 { 222 struct socket *wso = vp->v_fifoinfo->fi_writesock; 223 int error; 224 225 if (uio->uio_rw != UIO_WRITE) 226 panic("fifo_write mode"); 227 if (ioflag & IO_NDELAY) 228 wso->so_state |= SS_NBIO; 229 VOP_UNLOCK(vp); 230 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 231 VOP_LOCK(vp); 232 if (ioflag & IO_NDELAY) 233 wso->so_state &= ~SS_NBIO; 234 return (error); 235 } 236 237 /* 238 * Device ioctl operation. 239 */ 240 /* ARGSUSED */ 241 fifo_ioctl(vp, com, data, fflag, cred) 242 struct vnode *vp; 243 int com; 244 caddr_t data; 245 int fflag; 246 struct ucred *cred; 247 { 248 struct file filetmp; 249 int error; 250 251 if (com == FIONBIO) 252 return (0); 253 if (fflag & FREAD) 254 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 255 else 256 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 257 return (soo_ioctl(&filetmp, com, data)); 258 } 259 260 /* ARGSUSED */ 261 fifo_select(vp, which, fflag, cred) 262 struct vnode *vp; 263 int which, fflag; 264 struct ucred *cred; 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)); 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) 317 register struct vnode *vp; 318 int fflag; 319 struct ucred *cred; 320 { 321 register struct fifoinfo *fip = vp->v_fifoinfo; 322 int error1, error2; 323 324 if (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(vp) 348 struct vnode *vp; 349 { 350 351 printf("tag VT_NON"); 352 fifo_printinfo(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 fifo_advlock(vp, id, op, fl, flags) 381 struct vnode *vp; 382 caddr_t id; 383 int op; 384 struct flock *fl; 385 int flags; 386 { 387 388 return (EOPNOTSUPP); 389 } 390 391 /* 392 * Fifo bad operation 393 */ 394 fifo_badop() 395 { 396 397 panic("fifo_badop called"); 398 /* NOTREACHED */ 399 } 400