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