140292Smckusick /* 240292Smckusick * Copyright (c) 1990 The Regents of the University of California. 340292Smckusick * All rights reserved. 440292Smckusick * 544430Sbostic * %sccs.include.redist.c% 640292Smckusick * 7*48014Smckusick * @(#)fifo_vnops.c 7.7 (Berkeley) 04/15/91 840292Smckusick */ 940292Smckusick 1040292Smckusick #include "param.h" 1140292Smckusick #include "time.h" 1240292Smckusick #include "namei.h" 1340292Smckusick #include "vnode.h" 1440292Smckusick #include "socket.h" 1540292Smckusick #include "socketvar.h" 1640292Smckusick #include "stat.h" 1747540Skarels #include "systm.h" 1840292Smckusick #include "ioctl.h" 1940292Smckusick #include "file.h" 20*48014Smckusick #include "fifo.h" 2140292Smckusick #include "errno.h" 2240292Smckusick #include "malloc.h" 2340292Smckusick 2440292Smckusick /* 2540292Smckusick * This structure is associated with the FIFO vnode and stores 2640292Smckusick * the state associated with the FIFO. 2740292Smckusick */ 2840292Smckusick struct fifoinfo { 2940292Smckusick struct socket *fi_readsock; 3040292Smckusick struct socket *fi_writesock; 3140292Smckusick long fi_readers; 3240292Smckusick long fi_writers; 3340292Smckusick }; 3440292Smckusick 3540292Smckusick struct vnodeops fifo_vnodeops = { 3640292Smckusick fifo_lookup, /* lookup */ 37*48014Smckusick fifo_create, /* create */ 38*48014Smckusick fifo_mknod, /* mknod */ 3940292Smckusick fifo_open, /* open */ 4040292Smckusick fifo_close, /* close */ 41*48014Smckusick fifo_access, /* access */ 42*48014Smckusick fifo_getattr, /* getattr */ 43*48014Smckusick fifo_setattr, /* setattr */ 4440292Smckusick fifo_read, /* read */ 4540292Smckusick fifo_write, /* write */ 4640292Smckusick fifo_ioctl, /* ioctl */ 4740292Smckusick fifo_select, /* select */ 48*48014Smckusick fifo_mmap, /* mmap */ 49*48014Smckusick fifo_fsync, /* fsync */ 50*48014Smckusick fifo_seek, /* seek */ 51*48014Smckusick fifo_remove, /* remove */ 52*48014Smckusick fifo_link, /* link */ 53*48014Smckusick fifo_rename, /* rename */ 54*48014Smckusick fifo_mkdir, /* mkdir */ 55*48014Smckusick fifo_rmdir, /* rmdir */ 56*48014Smckusick fifo_symlink, /* symlink */ 57*48014Smckusick fifo_readdir, /* readdir */ 58*48014Smckusick fifo_readlink, /* readlink */ 59*48014Smckusick fifo_abortop, /* abortop */ 60*48014Smckusick fifo_inactive, /* inactive */ 61*48014Smckusick fifo_reclaim, /* reclaim */ 6240292Smckusick fifo_lock, /* lock */ 6340292Smckusick fifo_unlock, /* unlock */ 6440292Smckusick fifo_bmap, /* bmap */ 65*48014Smckusick fifo_strategy, /* strategy */ 6640292Smckusick fifo_print, /* print */ 67*48014Smckusick fifo_islocked, /* islocked */ 6846198Smckusick fifo_advlock, /* advlock */ 6940292Smckusick }; 7040292Smckusick 7140292Smckusick /* 7240292Smckusick * Trivial lookup routine that always fails. 7340292Smckusick */ 74*48014Smckusick /* ARGSUSED */ 75*48014Smckusick fifo_lookup(vp, ndp, p) 7640292Smckusick struct vnode *vp; 7740292Smckusick struct nameidata *ndp; 78*48014Smckusick struct proc *p; 7940292Smckusick { 8040292Smckusick 8140292Smckusick ndp->ni_dvp = vp; 8240292Smckusick ndp->ni_vp = NULL; 8340292Smckusick return (ENOTDIR); 8440292Smckusick } 8540292Smckusick 8640292Smckusick /* 8740292Smckusick * Open called to set up a new instance of a fifo or 8840292Smckusick * to find an active instance of a fifo. 8940292Smckusick */ 9040292Smckusick /* ARGSUSED */ 91*48014Smckusick fifo_open(vp, mode, cred, p) 9240292Smckusick register struct vnode *vp; 9340292Smckusick int mode; 9440292Smckusick struct ucred *cred; 95*48014Smckusick struct proc *p; 9640292Smckusick { 9740292Smckusick register struct fifoinfo *fip; 9840292Smckusick struct socket *rso, *wso; 9940292Smckusick int error; 10040637Skarels static char openstr[] = "fifo"; 10140292Smckusick 10240292Smckusick if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 10340292Smckusick return (EINVAL); 10440292Smckusick if ((fip = vp->v_fifoinfo) == NULL) { 10540292Smckusick MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 10640292Smckusick vp->v_fifoinfo = fip; 10740655Smckusick if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 10840655Smckusick free(fip, M_VNODE); 10940655Smckusick vp->v_fifoinfo = NULL; 11040292Smckusick return (error); 11140655Smckusick } 11240292Smckusick fip->fi_readsock = rso; 11340292Smckusick if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 11440292Smckusick (void)soclose(rso); 11540655Smckusick free(fip, M_VNODE); 11640655Smckusick vp->v_fifoinfo = NULL; 11740292Smckusick return (error); 11840292Smckusick } 11940292Smckusick fip->fi_writesock = wso; 12040292Smckusick if (error = unp_connect2(wso, rso)) { 12140292Smckusick (void)soclose(wso); 12240292Smckusick (void)soclose(rso); 12340655Smckusick free(fip, M_VNODE); 12440655Smckusick vp->v_fifoinfo = NULL; 12540292Smckusick return (error); 12640292Smckusick } 12740292Smckusick wso->so_state |= SS_CANTRCVMORE; 12840292Smckusick rso->so_state |= SS_CANTSENDMORE; 12940292Smckusick } 13040292Smckusick error = 0; 13140292Smckusick if (mode & FREAD) { 13240292Smckusick fip->fi_readers++; 13340292Smckusick if (fip->fi_readers == 1) { 13440292Smckusick fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 13540292Smckusick if (fip->fi_writers > 0) 13640292Smckusick wakeup((caddr_t)&fip->fi_writers); 13740292Smckusick } 13840292Smckusick if (mode & O_NONBLOCK) 13940292Smckusick return (0); 14040292Smckusick while (fip->fi_writers == 0) 14140637Skarels if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 14240637Skarels openstr, 0)) 14340292Smckusick break; 14440292Smckusick } else { 14540292Smckusick fip->fi_writers++; 14640292Smckusick if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 14740292Smckusick error = ENXIO; 14840292Smckusick } else { 14940292Smckusick if (fip->fi_writers == 1) { 15040292Smckusick fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 15140292Smckusick if (fip->fi_readers > 0) 15240292Smckusick wakeup((caddr_t)&fip->fi_readers); 15340292Smckusick } 15440292Smckusick while (fip->fi_readers == 0) 15540637Skarels if (error = tsleep((caddr_t)&fip->fi_writers, 15640637Skarels PSOCK, openstr, 0)) 15740292Smckusick break; 15840292Smckusick } 15940292Smckusick } 16040292Smckusick if (error) 161*48014Smckusick fifo_close(vp, mode, cred, p); 16240292Smckusick return (error); 16340292Smckusick } 16440292Smckusick 16540292Smckusick /* 16640292Smckusick * Vnode op for read 16740292Smckusick */ 16840292Smckusick /* ARGSUSED */ 16940292Smckusick fifo_read(vp, uio, ioflag, cred) 17040292Smckusick struct vnode *vp; 17140292Smckusick register struct uio *uio; 17240292Smckusick int ioflag; 17340292Smckusick struct ucred *cred; 17440292Smckusick { 17540292Smckusick register struct socket *rso = vp->v_fifoinfo->fi_readsock; 17640292Smckusick int error, startresid; 17740292Smckusick 178*48014Smckusick #ifdef DIAGNOSTIC 17940292Smckusick if (uio->uio_rw != UIO_READ) 18040292Smckusick panic("fifo_read mode"); 181*48014Smckusick #endif 18240292Smckusick if (uio->uio_resid == 0) 18340292Smckusick return (0); 18440292Smckusick if (ioflag & IO_NDELAY) 18540292Smckusick rso->so_state |= SS_NBIO; 18640292Smckusick startresid = uio->uio_resid; 18740292Smckusick VOP_UNLOCK(vp); 18840292Smckusick error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 18940292Smckusick (struct mbuf **)0, (struct mbuf **)0); 19040292Smckusick VOP_LOCK(vp); 19140292Smckusick /* 19240292Smckusick * Clear EOF indication after first such return. 19340292Smckusick */ 19440292Smckusick if (uio->uio_resid == startresid) 19540292Smckusick rso->so_state &= ~SS_CANTRCVMORE; 19640292Smckusick if (ioflag & IO_NDELAY) 19740292Smckusick rso->so_state &= ~SS_NBIO; 19840292Smckusick return (error); 19940292Smckusick } 20040292Smckusick 20140292Smckusick /* 20240292Smckusick * Vnode op for write 20340292Smckusick */ 20440292Smckusick /* ARGSUSED */ 20540292Smckusick fifo_write(vp, uio, ioflag, cred) 20640292Smckusick struct vnode *vp; 20740292Smckusick register struct uio *uio; 20840292Smckusick int ioflag; 20940292Smckusick struct ucred *cred; 21040292Smckusick { 21140292Smckusick struct socket *wso = vp->v_fifoinfo->fi_writesock; 21240292Smckusick int error; 21340292Smckusick 214*48014Smckusick #ifdef DIAGNOSTIC 21540292Smckusick if (uio->uio_rw != UIO_WRITE) 21640292Smckusick panic("fifo_write mode"); 217*48014Smckusick #endif 21840292Smckusick if (ioflag & IO_NDELAY) 21940292Smckusick wso->so_state |= SS_NBIO; 22040292Smckusick VOP_UNLOCK(vp); 22140292Smckusick error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 22240292Smckusick VOP_LOCK(vp); 22340292Smckusick if (ioflag & IO_NDELAY) 22440292Smckusick wso->so_state &= ~SS_NBIO; 22540292Smckusick return (error); 22640292Smckusick } 22740292Smckusick 22840292Smckusick /* 22940292Smckusick * Device ioctl operation. 23040292Smckusick */ 23140292Smckusick /* ARGSUSED */ 232*48014Smckusick fifo_ioctl(vp, com, data, fflag, cred, p) 23340292Smckusick struct vnode *vp; 23440292Smckusick int com; 23540292Smckusick caddr_t data; 23640292Smckusick int fflag; 23740292Smckusick struct ucred *cred; 238*48014Smckusick struct proc *p; 23940292Smckusick { 24040292Smckusick struct file filetmp; 24140292Smckusick int error; 24240292Smckusick 24340292Smckusick if (com == FIONBIO) 24440292Smckusick return (0); 24540292Smckusick if (fflag & FREAD) 24640292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 24740292Smckusick else 24840292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 249*48014Smckusick return (soo_ioctl(&filetmp, com, data, p)); 25040292Smckusick } 25140292Smckusick 25240292Smckusick /* ARGSUSED */ 253*48014Smckusick fifo_select(vp, which, fflag, cred, p) 25440292Smckusick struct vnode *vp; 25540292Smckusick int which, fflag; 25640292Smckusick struct ucred *cred; 257*48014Smckusick struct proc *p; 25840292Smckusick { 25940292Smckusick struct file filetmp; 26040292Smckusick int error; 26140292Smckusick 26240292Smckusick if (fflag & FREAD) 26340292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 26440292Smckusick else 26540292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 266*48014Smckusick return (soo_select(&filetmp, which, p)); 26740292Smckusick } 26840292Smckusick 26940292Smckusick /* 27040292Smckusick * This is a noop, simply returning what one has been given. 27140292Smckusick */ 27240292Smckusick fifo_bmap(vp, bn, vpp, bnp) 27340292Smckusick struct vnode *vp; 27440292Smckusick daddr_t bn; 27540292Smckusick struct vnode **vpp; 27640292Smckusick daddr_t *bnp; 27740292Smckusick { 27840292Smckusick 27940292Smckusick if (vpp != NULL) 28040292Smckusick *vpp = vp; 28140292Smckusick if (bnp != NULL) 28240292Smckusick *bnp = bn; 28340292Smckusick return (0); 28440292Smckusick } 28540292Smckusick 28640292Smckusick /* 28740292Smckusick * At the moment we do not do any locking. 28840292Smckusick */ 28940292Smckusick /* ARGSUSED */ 29040292Smckusick fifo_lock(vp) 29140292Smckusick struct vnode *vp; 29240292Smckusick { 29340292Smckusick 29440292Smckusick return (0); 29540292Smckusick } 29640292Smckusick 29740292Smckusick /* ARGSUSED */ 29840292Smckusick fifo_unlock(vp) 29940292Smckusick struct vnode *vp; 30040292Smckusick { 30140292Smckusick 30240292Smckusick return (0); 30340292Smckusick } 30440292Smckusick 30540292Smckusick /* 30640292Smckusick * Device close routine 30740292Smckusick */ 30840292Smckusick /* ARGSUSED */ 309*48014Smckusick fifo_close(vp, fflag, cred, p) 31040292Smckusick register struct vnode *vp; 31140292Smckusick int fflag; 31240292Smckusick struct ucred *cred; 313*48014Smckusick struct proc *p; 31440292Smckusick { 31540292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 31640292Smckusick int error1, error2; 31740292Smckusick 31840292Smckusick if (fflag & FWRITE) { 31940292Smckusick fip->fi_writers--; 32040292Smckusick if (fip->fi_writers == 0) 32140292Smckusick socantrcvmore(fip->fi_readsock); 32240292Smckusick } else { 32340292Smckusick fip->fi_readers--; 32440292Smckusick if (fip->fi_readers == 0) 32540292Smckusick socantsendmore(fip->fi_writesock); 32640292Smckusick } 32740292Smckusick if (vp->v_usecount > 1) 32840292Smckusick return (0); 32940292Smckusick error1 = soclose(fip->fi_readsock); 33040292Smckusick error2 = soclose(fip->fi_writesock); 33140292Smckusick FREE(fip, M_VNODE); 33240292Smckusick vp->v_fifoinfo = NULL; 33340292Smckusick if (error1) 33440292Smckusick return (error1); 33540292Smckusick return (error2); 33640292Smckusick } 33740292Smckusick 33840292Smckusick /* 33940292Smckusick * Print out the contents of a fifo vnode. 34040292Smckusick */ 34140292Smckusick fifo_print(vp) 34240292Smckusick struct vnode *vp; 34340292Smckusick { 34440292Smckusick 34540292Smckusick printf("tag VT_NON"); 34640292Smckusick fifo_printinfo(vp); 34740292Smckusick printf("\n"); 34840292Smckusick } 34940292Smckusick 35040292Smckusick /* 35140292Smckusick * Print out internal contents of a fifo vnode. 35240292Smckusick */ 35340292Smckusick fifo_printinfo(vp) 35440292Smckusick struct vnode *vp; 35540292Smckusick { 35640292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 35740292Smckusick 35840292Smckusick printf(", fifo with %d readers and %d writers", 35940292Smckusick fip->fi_readers, fip->fi_writers); 36040292Smckusick } 36140292Smckusick 36240292Smckusick /* 36340292Smckusick * Fifo failed operation 36440292Smckusick */ 36540292Smckusick fifo_ebadf() 36640292Smckusick { 36740292Smckusick 36840292Smckusick return (EBADF); 36940292Smckusick } 37040292Smckusick 37140292Smckusick /* 37246198Smckusick * Fifo advisory byte-level locks. 37346198Smckusick */ 374*48014Smckusick /* ARGSUSED */ 37546198Smckusick fifo_advlock(vp, id, op, fl, flags) 37646198Smckusick struct vnode *vp; 37746198Smckusick caddr_t id; 37846198Smckusick int op; 37946198Smckusick struct flock *fl; 38046198Smckusick int flags; 38146198Smckusick { 38246198Smckusick 38346198Smckusick return (EOPNOTSUPP); 38446198Smckusick } 38546198Smckusick 38646198Smckusick /* 38740292Smckusick * Fifo bad operation 38840292Smckusick */ 38940292Smckusick fifo_badop() 39040292Smckusick { 39140292Smckusick 39240292Smckusick panic("fifo_badop called"); 39340292Smckusick /* NOTREACHED */ 39440292Smckusick } 395