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