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