1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91 34 */ 35 36 #include "param.h" 37 #include "time.h" 38 #include "namei.h" 39 #include "vnode.h" 40 #include "socket.h" 41 #include "socketvar.h" 42 #include "stat.h" 43 #include "systm.h" 44 #include "ioctl.h" 45 #include "file.h" 46 #include "fifo.h" 47 #include "errno.h" 48 #include "malloc.h" 49 50 /* 51 * This structure is associated with the FIFO vnode and stores 52 * the state associated with the FIFO. 53 */ 54 struct fifoinfo { 55 struct socket *fi_readsock; 56 struct socket *fi_writesock; 57 long fi_readers; 58 long fi_writers; 59 }; 60 61 struct vnodeops fifo_vnodeops = { 62 fifo_lookup, /* lookup */ 63 fifo_create, /* create */ 64 fifo_mknod, /* mknod */ 65 fifo_open, /* open */ 66 fifo_close, /* close */ 67 fifo_access, /* access */ 68 fifo_getattr, /* getattr */ 69 fifo_setattr, /* setattr */ 70 fifo_read, /* read */ 71 fifo_write, /* write */ 72 fifo_ioctl, /* ioctl */ 73 fifo_select, /* select */ 74 fifo_mmap, /* mmap */ 75 fifo_fsync, /* fsync */ 76 fifo_seek, /* seek */ 77 fifo_remove, /* remove */ 78 fifo_link, /* link */ 79 fifo_rename, /* rename */ 80 fifo_mkdir, /* mkdir */ 81 fifo_rmdir, /* rmdir */ 82 fifo_symlink, /* symlink */ 83 fifo_readdir, /* readdir */ 84 fifo_readlink, /* readlink */ 85 fifo_abortop, /* abortop */ 86 fifo_inactive, /* inactive */ 87 fifo_reclaim, /* reclaim */ 88 fifo_lock, /* lock */ 89 fifo_unlock, /* unlock */ 90 fifo_bmap, /* bmap */ 91 fifo_strategy, /* strategy */ 92 fifo_print, /* print */ 93 fifo_islocked, /* islocked */ 94 fifo_advlock, /* advlock */ 95 }; 96 97 /* 98 * Trivial lookup routine that always fails. 99 */ 100 /* ARGSUSED */ 101 fifo_lookup(vp, ndp, p) 102 struct vnode *vp; 103 struct nameidata *ndp; 104 struct proc *p; 105 { 106 107 ndp->ni_dvp = vp; 108 ndp->ni_vp = NULL; 109 return (ENOTDIR); 110 } 111 112 /* 113 * Open called to set up a new instance of a fifo or 114 * to find an active instance of a fifo. 115 */ 116 /* ARGSUSED */ 117 fifo_open(vp, mode, cred, p) 118 register struct vnode *vp; 119 int mode; 120 struct ucred *cred; 121 struct proc *p; 122 { 123 register struct fifoinfo *fip; 124 struct socket *rso, *wso; 125 int error; 126 static char openstr[] = "fifo"; 127 128 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 129 return (EINVAL); 130 if ((fip = vp->v_fifoinfo) == NULL) { 131 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 132 vp->v_fifoinfo = fip; 133 fip->fi_readers=0; 134 fip->fi_writers=0; 135 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 136 free(fip, M_VNODE); 137 vp->v_fifoinfo = NULL; 138 return (error); 139 } 140 fip->fi_readsock = rso; 141 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 142 (void)soclose(rso); 143 free(fip, M_VNODE); 144 vp->v_fifoinfo = NULL; 145 return (error); 146 } 147 fip->fi_writesock = wso; 148 if (error = unp_connect2(wso, rso)) { 149 (void)soclose(wso); 150 (void)soclose(rso); 151 free(fip, M_VNODE); 152 vp->v_fifoinfo = NULL; 153 return (error); 154 } 155 wso->so_state |= SS_CANTRCVMORE; 156 rso->so_state |= SS_CANTSENDMORE; 157 } 158 error = 0; 159 if (mode & FREAD) { 160 fip->fi_readers++; 161 if (fip->fi_readers == 1) { 162 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 163 if (fip->fi_writers > 0) 164 wakeup((caddr_t)&fip->fi_writers); 165 } 166 if (mode & O_NONBLOCK) 167 return (0); 168 while (fip->fi_writers == 0) { 169 VOP_UNLOCK(vp); 170 error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 171 openstr, 0); 172 VOP_LOCK(vp); 173 if(error) 174 break; 175 } 176 } else { 177 fip->fi_writers++; 178 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 179 error = ENXIO; 180 } else { 181 if (fip->fi_writers == 1) { 182 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 183 if (fip->fi_readers > 0) 184 wakeup((caddr_t)&fip->fi_readers); 185 } 186 while (fip->fi_readers == 0) { 187 VOP_UNLOCK(vp); 188 error = tsleep((caddr_t)&fip->fi_writers, 189 PSOCK, openstr, 0); 190 VOP_LOCK(vp); 191 if(error) 192 break; 193 } 194 } 195 } 196 if (error) 197 fifo_close(vp, mode, cred, p); 198 return (error); 199 } 200 201 /* 202 * Vnode op for read 203 */ 204 /* ARGSUSED */ 205 fifo_read(vp, uio, ioflag, cred) 206 struct vnode *vp; 207 register struct uio *uio; 208 int ioflag; 209 struct ucred *cred; 210 { 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 237 /* 238 * Vnode op for write 239 */ 240 /* ARGSUSED */ 241 fifo_write(vp, uio, ioflag, cred) 242 struct vnode *vp; 243 register struct uio *uio; 244 int ioflag; 245 struct ucred *cred; 246 { 247 struct socket *wso = vp->v_fifoinfo->fi_writesock; 248 int error; 249 250 #ifdef DIAGNOSTIC 251 if (uio->uio_rw != UIO_WRITE) 252 panic("fifo_write mode"); 253 #endif 254 if (ioflag & IO_NDELAY) 255 wso->so_state |= SS_NBIO; 256 VOP_UNLOCK(vp); 257 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 258 VOP_LOCK(vp); 259 if (ioflag & IO_NDELAY) 260 wso->so_state &= ~SS_NBIO; 261 return (error); 262 } 263 264 /* 265 * Device ioctl operation. 266 */ 267 /* ARGSUSED */ 268 fifo_ioctl(vp, com, data, fflag, cred, p) 269 struct vnode *vp; 270 int com; 271 caddr_t data; 272 int fflag; 273 struct ucred *cred; 274 struct proc *p; 275 { 276 struct file filetmp; 277 int error; 278 279 if (com == FIONBIO) 280 return (0); 281 if (fflag & FREAD) 282 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 283 else 284 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 285 return (soo_ioctl(&filetmp, com, data, p)); 286 } 287 288 /* ARGSUSED */ 289 fifo_select(vp, which, fflag, cred, p) 290 struct vnode *vp; 291 int which, fflag; 292 struct ucred *cred; 293 struct proc *p; 294 { 295 struct file filetmp; 296 int error; 297 298 if (fflag & FREAD) 299 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 300 else 301 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 302 return (soo_select(&filetmp, which, p)); 303 } 304 305 /* 306 * This is a noop, simply returning what one has been given. 307 */ 308 fifo_bmap(vp, bn, vpp, bnp) 309 struct vnode *vp; 310 daddr_t bn; 311 struct vnode **vpp; 312 daddr_t *bnp; 313 { 314 315 if (vpp != NULL) 316 *vpp = vp; 317 if (bnp != NULL) 318 *bnp = bn; 319 return (0); 320 } 321 322 /* 323 * At the moment we do not do any locking. 324 */ 325 /* ARGSUSED */ 326 fifo_lock(vp) 327 struct vnode *vp; 328 { 329 330 return (0); 331 } 332 333 /* ARGSUSED */ 334 fifo_unlock(vp) 335 struct vnode *vp; 336 { 337 338 return (0); 339 } 340 341 /* 342 * Device close routine 343 */ 344 /* ARGSUSED */ 345 fifo_close(vp, fflag, cred, p) 346 register struct vnode *vp; 347 int fflag; 348 struct ucred *cred; 349 struct proc *p; 350 { 351 register struct fifoinfo *fip = vp->v_fifoinfo; 352 int error1, error2; 353 354 if (fflag & FWRITE) { 355 fip->fi_writers--; 356 if (fip->fi_writers == 0) 357 socantrcvmore(fip->fi_readsock); 358 } else { 359 fip->fi_readers--; 360 if (fip->fi_readers == 0) 361 socantsendmore(fip->fi_writesock); 362 } 363 if (vp->v_usecount > 1) 364 return (0); 365 error1 = soclose(fip->fi_readsock); 366 error2 = soclose(fip->fi_writesock); 367 FREE(fip, M_VNODE); 368 vp->v_fifoinfo = NULL; 369 if (error1) 370 return (error1); 371 return (error2); 372 } 373 374 /* 375 * Print out the contents of a fifo vnode. 376 */ 377 fifo_print(vp) 378 struct vnode *vp; 379 { 380 381 printf("tag VT_NON"); 382 fifo_printinfo(vp); 383 printf("\n"); 384 } 385 386 /* 387 * Print out internal contents of a fifo vnode. 388 */ 389 fifo_printinfo(vp) 390 struct vnode *vp; 391 { 392 register struct fifoinfo *fip = vp->v_fifoinfo; 393 394 printf(", fifo with %d readers and %d writers", 395 fip->fi_readers, fip->fi_writers); 396 } 397 398 /* 399 * Fifo failed operation 400 */ 401 fifo_ebadf() 402 { 403 404 return (EBADF); 405 } 406 407 /* 408 * Fifo advisory byte-level locks. 409 */ 410 /* ARGSUSED */ 411 fifo_advlock(vp, id, op, fl, flags) 412 struct vnode *vp; 413 caddr_t id; 414 int op; 415 struct flock *fl; 416 int flags; 417 { 418 419 return (EOPNOTSUPP); 420 } 421 422 /* 423 * Fifo bad operation 424 */ 425 fifo_badop() 426 { 427 428 panic("fifo_badop called"); 429 /* NOTREACHED */ 430 } 431