1*40292Smckusick /* 2*40292Smckusick * Copyright (c) 1990 The Regents of the University of California. 3*40292Smckusick * All rights reserved. 4*40292Smckusick * 5*40292Smckusick * Redistribution and use in source and binary forms are permitted 6*40292Smckusick * provided that the above copyright notice and this paragraph are 7*40292Smckusick * duplicated in all such forms and that any documentation, 8*40292Smckusick * advertising materials, and other materials related to such 9*40292Smckusick * distribution and use acknowledge that the software was developed 10*40292Smckusick * by the University of California, Berkeley. The name of the 11*40292Smckusick * University may not be used to endorse or promote products derived 12*40292Smckusick * from this software without specific prior written permission. 13*40292Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*40292Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*40292Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*40292Smckusick * 17*40292Smckusick * @(#)fifo_vnops.c 7.1 (Berkeley) 03/05/90 18*40292Smckusick */ 19*40292Smckusick 20*40292Smckusick #include "param.h" 21*40292Smckusick #include "time.h" 22*40292Smckusick #include "namei.h" 23*40292Smckusick #include "vnode.h" 24*40292Smckusick #include "socket.h" 25*40292Smckusick #include "socketvar.h" 26*40292Smckusick #include "stat.h" 27*40292Smckusick #include "ioctl.h" 28*40292Smckusick #include "file.h" 29*40292Smckusick #include "errno.h" 30*40292Smckusick #include "malloc.h" 31*40292Smckusick 32*40292Smckusick /* 33*40292Smckusick * This structure is associated with the FIFO vnode and stores 34*40292Smckusick * the state associated with the FIFO. 35*40292Smckusick */ 36*40292Smckusick struct fifoinfo { 37*40292Smckusick struct socket *fi_readsock; 38*40292Smckusick struct socket *fi_writesock; 39*40292Smckusick long fi_readers; 40*40292Smckusick long fi_writers; 41*40292Smckusick }; 42*40292Smckusick 43*40292Smckusick int fifo_lookup(), 44*40292Smckusick fifo_open(), 45*40292Smckusick fifo_read(), 46*40292Smckusick fifo_write(), 47*40292Smckusick fifo_strategy(), 48*40292Smckusick fifo_bmap(), 49*40292Smckusick fifo_ioctl(), 50*40292Smckusick fifo_select(), 51*40292Smckusick fifo_lock(), 52*40292Smckusick fifo_unlock(), 53*40292Smckusick fifo_close(), 54*40292Smckusick fifo_print(), 55*40292Smckusick fifo_ebadf(), 56*40292Smckusick fifo_badop(), 57*40292Smckusick fifo_nullop(); 58*40292Smckusick 59*40292Smckusick struct vnodeops fifo_vnodeops = { 60*40292Smckusick fifo_lookup, /* lookup */ 61*40292Smckusick fifo_badop, /* create */ 62*40292Smckusick fifo_badop, /* mknod */ 63*40292Smckusick fifo_open, /* open */ 64*40292Smckusick fifo_close, /* close */ 65*40292Smckusick fifo_ebadf, /* access */ 66*40292Smckusick fifo_ebadf, /* getattr */ 67*40292Smckusick fifo_ebadf, /* setattr */ 68*40292Smckusick fifo_read, /* read */ 69*40292Smckusick fifo_write, /* write */ 70*40292Smckusick fifo_ioctl, /* ioctl */ 71*40292Smckusick fifo_select, /* select */ 72*40292Smckusick fifo_badop, /* mmap */ 73*40292Smckusick fifo_nullop, /* fsync */ 74*40292Smckusick fifo_badop, /* seek */ 75*40292Smckusick fifo_badop, /* remove */ 76*40292Smckusick fifo_badop, /* link */ 77*40292Smckusick fifo_badop, /* rename */ 78*40292Smckusick fifo_badop, /* mkdir */ 79*40292Smckusick fifo_badop, /* rmdir */ 80*40292Smckusick fifo_badop, /* symlink */ 81*40292Smckusick fifo_badop, /* readdir */ 82*40292Smckusick fifo_badop, /* readlink */ 83*40292Smckusick fifo_badop, /* abortop */ 84*40292Smckusick fifo_nullop, /* inactive */ 85*40292Smckusick fifo_nullop, /* reclaim */ 86*40292Smckusick fifo_lock, /* lock */ 87*40292Smckusick fifo_unlock, /* unlock */ 88*40292Smckusick fifo_bmap, /* bmap */ 89*40292Smckusick fifo_badop, /* strategy */ 90*40292Smckusick fifo_print, /* print */ 91*40292Smckusick fifo_nullop, /* islocked */ 92*40292Smckusick }; 93*40292Smckusick 94*40292Smckusick /* 95*40292Smckusick * Trivial lookup routine that always fails. 96*40292Smckusick */ 97*40292Smckusick fifo_lookup(vp, ndp) 98*40292Smckusick struct vnode *vp; 99*40292Smckusick struct nameidata *ndp; 100*40292Smckusick { 101*40292Smckusick 102*40292Smckusick ndp->ni_dvp = vp; 103*40292Smckusick ndp->ni_vp = NULL; 104*40292Smckusick return (ENOTDIR); 105*40292Smckusick } 106*40292Smckusick 107*40292Smckusick /* 108*40292Smckusick * Open called to set up a new instance of a fifo or 109*40292Smckusick * to find an active instance of a fifo. 110*40292Smckusick */ 111*40292Smckusick /* ARGSUSED */ 112*40292Smckusick fifo_open(vp, mode, cred) 113*40292Smckusick register struct vnode *vp; 114*40292Smckusick int mode; 115*40292Smckusick struct ucred *cred; 116*40292Smckusick { 117*40292Smckusick register struct fifoinfo *fip; 118*40292Smckusick struct socket *rso, *wso; 119*40292Smckusick int error; 120*40292Smckusick 121*40292Smckusick if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 122*40292Smckusick return (EINVAL); 123*40292Smckusick if ((fip = vp->v_fifoinfo) == NULL) { 124*40292Smckusick MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 125*40292Smckusick vp->v_fifoinfo = fip; 126*40292Smckusick if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) 127*40292Smckusick return (error); 128*40292Smckusick fip->fi_readsock = rso; 129*40292Smckusick if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 130*40292Smckusick (void)soclose(rso); 131*40292Smckusick return (error); 132*40292Smckusick } 133*40292Smckusick fip->fi_writesock = wso; 134*40292Smckusick if (error = unp_connect2(wso, rso)) { 135*40292Smckusick (void)soclose(wso); 136*40292Smckusick (void)soclose(rso); 137*40292Smckusick return (error); 138*40292Smckusick } 139*40292Smckusick wso->so_state |= SS_CANTRCVMORE; 140*40292Smckusick rso->so_state |= SS_CANTSENDMORE; 141*40292Smckusick } 142*40292Smckusick error = 0; 143*40292Smckusick if (mode & FREAD) { 144*40292Smckusick fip->fi_readers++; 145*40292Smckusick if (fip->fi_readers == 1) { 146*40292Smckusick fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 147*40292Smckusick if (fip->fi_writers > 0) 148*40292Smckusick wakeup((caddr_t)&fip->fi_writers); 149*40292Smckusick } 150*40292Smckusick if (mode & O_NONBLOCK) 151*40292Smckusick return (0); 152*40292Smckusick while (fip->fi_writers == 0) 153*40292Smckusick if (error = isleep((caddr_t)&fip->fi_readers, PZERO + 1, 154*40292Smckusick SLP_FIFO_OPEN, 0)) 155*40292Smckusick break; 156*40292Smckusick } else { 157*40292Smckusick fip->fi_writers++; 158*40292Smckusick if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 159*40292Smckusick error = ENXIO; 160*40292Smckusick } else { 161*40292Smckusick if (fip->fi_writers == 1) { 162*40292Smckusick fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 163*40292Smckusick if (fip->fi_readers > 0) 164*40292Smckusick wakeup((caddr_t)&fip->fi_readers); 165*40292Smckusick } 166*40292Smckusick while (fip->fi_readers == 0) 167*40292Smckusick if (error = isleep((caddr_t)&fip->fi_writers, 168*40292Smckusick PZERO + 1, SLP_FIFO_OPEN, 0)) 169*40292Smckusick break; 170*40292Smckusick } 171*40292Smckusick } 172*40292Smckusick if (error) 173*40292Smckusick fifo_close(vp, mode, cred); 174*40292Smckusick return (error); 175*40292Smckusick } 176*40292Smckusick 177*40292Smckusick /* 178*40292Smckusick * Vnode op for read 179*40292Smckusick */ 180*40292Smckusick /* ARGSUSED */ 181*40292Smckusick fifo_read(vp, uio, ioflag, cred) 182*40292Smckusick struct vnode *vp; 183*40292Smckusick register struct uio *uio; 184*40292Smckusick int ioflag; 185*40292Smckusick struct ucred *cred; 186*40292Smckusick { 187*40292Smckusick register struct socket *rso = vp->v_fifoinfo->fi_readsock; 188*40292Smckusick int error, startresid; 189*40292Smckusick 190*40292Smckusick if (uio->uio_rw != UIO_READ) 191*40292Smckusick panic("fifo_read mode"); 192*40292Smckusick if (uio->uio_resid == 0) 193*40292Smckusick return (0); 194*40292Smckusick if (ioflag & IO_NDELAY) 195*40292Smckusick rso->so_state |= SS_NBIO; 196*40292Smckusick startresid = uio->uio_resid; 197*40292Smckusick VOP_UNLOCK(vp); 198*40292Smckusick error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 199*40292Smckusick (struct mbuf **)0, (struct mbuf **)0); 200*40292Smckusick VOP_LOCK(vp); 201*40292Smckusick /* 202*40292Smckusick * Clear EOF indication after first such return. 203*40292Smckusick */ 204*40292Smckusick if (uio->uio_resid == startresid) 205*40292Smckusick rso->so_state &= ~SS_CANTRCVMORE; 206*40292Smckusick if (ioflag & IO_NDELAY) 207*40292Smckusick rso->so_state &= ~SS_NBIO; 208*40292Smckusick return (error); 209*40292Smckusick } 210*40292Smckusick 211*40292Smckusick /* 212*40292Smckusick * Vnode op for write 213*40292Smckusick */ 214*40292Smckusick /* ARGSUSED */ 215*40292Smckusick fifo_write(vp, uio, ioflag, cred) 216*40292Smckusick struct vnode *vp; 217*40292Smckusick register struct uio *uio; 218*40292Smckusick int ioflag; 219*40292Smckusick struct ucred *cred; 220*40292Smckusick { 221*40292Smckusick struct socket *wso = vp->v_fifoinfo->fi_writesock; 222*40292Smckusick int error; 223*40292Smckusick 224*40292Smckusick if (uio->uio_rw != UIO_WRITE) 225*40292Smckusick panic("fifo_write mode"); 226*40292Smckusick if (ioflag & IO_NDELAY) 227*40292Smckusick wso->so_state |= SS_NBIO; 228*40292Smckusick VOP_UNLOCK(vp); 229*40292Smckusick error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 230*40292Smckusick VOP_LOCK(vp); 231*40292Smckusick if (ioflag & IO_NDELAY) 232*40292Smckusick wso->so_state &= ~SS_NBIO; 233*40292Smckusick return (error); 234*40292Smckusick } 235*40292Smckusick 236*40292Smckusick /* 237*40292Smckusick * Device ioctl operation. 238*40292Smckusick */ 239*40292Smckusick /* ARGSUSED */ 240*40292Smckusick fifo_ioctl(vp, com, data, fflag, cred) 241*40292Smckusick struct vnode *vp; 242*40292Smckusick int com; 243*40292Smckusick caddr_t data; 244*40292Smckusick int fflag; 245*40292Smckusick struct ucred *cred; 246*40292Smckusick { 247*40292Smckusick struct file filetmp; 248*40292Smckusick int error; 249*40292Smckusick 250*40292Smckusick if (com == FIONBIO) 251*40292Smckusick return (0); 252*40292Smckusick if (fflag & FREAD) 253*40292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 254*40292Smckusick else 255*40292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 256*40292Smckusick return (soo_ioctl(&filetmp, com, data)); 257*40292Smckusick } 258*40292Smckusick 259*40292Smckusick /* ARGSUSED */ 260*40292Smckusick fifo_select(vp, which, fflag, cred) 261*40292Smckusick struct vnode *vp; 262*40292Smckusick int which, fflag; 263*40292Smckusick struct ucred *cred; 264*40292Smckusick { 265*40292Smckusick struct file filetmp; 266*40292Smckusick int error; 267*40292Smckusick 268*40292Smckusick if (fflag & FREAD) 269*40292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 270*40292Smckusick else 271*40292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 272*40292Smckusick return (soo_select(&filetmp, which)); 273*40292Smckusick } 274*40292Smckusick 275*40292Smckusick /* 276*40292Smckusick * This is a noop, simply returning what one has been given. 277*40292Smckusick */ 278*40292Smckusick fifo_bmap(vp, bn, vpp, bnp) 279*40292Smckusick struct vnode *vp; 280*40292Smckusick daddr_t bn; 281*40292Smckusick struct vnode **vpp; 282*40292Smckusick daddr_t *bnp; 283*40292Smckusick { 284*40292Smckusick 285*40292Smckusick if (vpp != NULL) 286*40292Smckusick *vpp = vp; 287*40292Smckusick if (bnp != NULL) 288*40292Smckusick *bnp = bn; 289*40292Smckusick return (0); 290*40292Smckusick } 291*40292Smckusick 292*40292Smckusick /* 293*40292Smckusick * At the moment we do not do any locking. 294*40292Smckusick */ 295*40292Smckusick /* ARGSUSED */ 296*40292Smckusick fifo_lock(vp) 297*40292Smckusick struct vnode *vp; 298*40292Smckusick { 299*40292Smckusick 300*40292Smckusick return (0); 301*40292Smckusick } 302*40292Smckusick 303*40292Smckusick /* ARGSUSED */ 304*40292Smckusick fifo_unlock(vp) 305*40292Smckusick struct vnode *vp; 306*40292Smckusick { 307*40292Smckusick 308*40292Smckusick return (0); 309*40292Smckusick } 310*40292Smckusick 311*40292Smckusick /* 312*40292Smckusick * Device close routine 313*40292Smckusick */ 314*40292Smckusick /* ARGSUSED */ 315*40292Smckusick fifo_close(vp, fflag, cred) 316*40292Smckusick register struct vnode *vp; 317*40292Smckusick int fflag; 318*40292Smckusick struct ucred *cred; 319*40292Smckusick { 320*40292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 321*40292Smckusick int error1, error2; 322*40292Smckusick 323*40292Smckusick if (fflag & FWRITE) { 324*40292Smckusick fip->fi_writers--; 325*40292Smckusick if (fip->fi_writers == 0) 326*40292Smckusick socantrcvmore(fip->fi_readsock); 327*40292Smckusick } else { 328*40292Smckusick fip->fi_readers--; 329*40292Smckusick if (fip->fi_readers == 0) 330*40292Smckusick socantsendmore(fip->fi_writesock); 331*40292Smckusick } 332*40292Smckusick if (vp->v_usecount > 1) 333*40292Smckusick return (0); 334*40292Smckusick error1 = soclose(fip->fi_readsock); 335*40292Smckusick error2 = soclose(fip->fi_writesock); 336*40292Smckusick FREE(fip, M_VNODE); 337*40292Smckusick vp->v_fifoinfo = NULL; 338*40292Smckusick if (error1) 339*40292Smckusick return (error1); 340*40292Smckusick return (error2); 341*40292Smckusick } 342*40292Smckusick 343*40292Smckusick /* 344*40292Smckusick * Print out the contents of a fifo vnode. 345*40292Smckusick */ 346*40292Smckusick fifo_print(vp) 347*40292Smckusick struct vnode *vp; 348*40292Smckusick { 349*40292Smckusick 350*40292Smckusick printf("tag VT_NON"); 351*40292Smckusick fifo_printinfo(vp); 352*40292Smckusick printf("\n"); 353*40292Smckusick } 354*40292Smckusick 355*40292Smckusick /* 356*40292Smckusick * Print out internal contents of a fifo vnode. 357*40292Smckusick */ 358*40292Smckusick fifo_printinfo(vp) 359*40292Smckusick struct vnode *vp; 360*40292Smckusick { 361*40292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 362*40292Smckusick 363*40292Smckusick printf(", fifo with %d readers and %d writers", 364*40292Smckusick fip->fi_readers, fip->fi_writers); 365*40292Smckusick } 366*40292Smckusick 367*40292Smckusick /* 368*40292Smckusick * Fifo failed operation 369*40292Smckusick */ 370*40292Smckusick fifo_ebadf() 371*40292Smckusick { 372*40292Smckusick 373*40292Smckusick return (EBADF); 374*40292Smckusick } 375*40292Smckusick 376*40292Smckusick /* 377*40292Smckusick * Fifo bad operation 378*40292Smckusick */ 379*40292Smckusick fifo_badop() 380*40292Smckusick { 381*40292Smckusick 382*40292Smckusick panic("fifo_badop called"); 383*40292Smckusick /* NOTREACHED */ 384*40292Smckusick } 385*40292Smckusick 386*40292Smckusick /* 387*40292Smckusick * Fifo null operation 388*40292Smckusick */ 389*40292Smckusick fifo_nullop() 390*40292Smckusick { 391*40292Smckusick 392*40292Smckusick return (0); 393*40292Smckusick } 394