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