140292Smckusick /* 240292Smckusick * Copyright (c) 1990 The Regents of the University of California. 340292Smckusick * All rights reserved. 440292Smckusick * 544430Sbostic * %sccs.include.redist.c% 640292Smckusick * 7*52305Sheideman * @(#)fifo_vnops.c 7.9 (Berkeley) 02/03/92 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" 2048014Smckusick #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 */ 3748014Smckusick fifo_create, /* create */ 3848014Smckusick fifo_mknod, /* mknod */ 3940292Smckusick fifo_open, /* open */ 4040292Smckusick fifo_close, /* close */ 4148014Smckusick fifo_access, /* access */ 4248014Smckusick fifo_getattr, /* getattr */ 4348014Smckusick fifo_setattr, /* setattr */ 4440292Smckusick fifo_read, /* read */ 4540292Smckusick fifo_write, /* write */ 4640292Smckusick fifo_ioctl, /* ioctl */ 4740292Smckusick fifo_select, /* select */ 4848014Smckusick fifo_mmap, /* mmap */ 4948014Smckusick fifo_fsync, /* fsync */ 5048014Smckusick fifo_seek, /* seek */ 5148014Smckusick fifo_remove, /* remove */ 5248014Smckusick fifo_link, /* link */ 5348014Smckusick fifo_rename, /* rename */ 5448014Smckusick fifo_mkdir, /* mkdir */ 5548014Smckusick fifo_rmdir, /* rmdir */ 5648014Smckusick fifo_symlink, /* symlink */ 5748014Smckusick fifo_readdir, /* readdir */ 5848014Smckusick fifo_readlink, /* readlink */ 5948014Smckusick fifo_abortop, /* abortop */ 6048014Smckusick fifo_inactive, /* inactive */ 6148014Smckusick fifo_reclaim, /* reclaim */ 6240292Smckusick fifo_lock, /* lock */ 6340292Smckusick fifo_unlock, /* unlock */ 6440292Smckusick fifo_bmap, /* bmap */ 6548014Smckusick fifo_strategy, /* strategy */ 6640292Smckusick fifo_print, /* print */ 6748014Smckusick fifo_islocked, /* islocked */ 6846198Smckusick fifo_advlock, /* advlock */ 6951566Smckusick fifo_blkatoff, /* blkatoff */ 7051566Smckusick fifo_vget, /* vget */ 7151566Smckusick fifo_valloc, /* valloc */ 7251566Smckusick fifo_vfree, /* vfree */ 7351566Smckusick fifo_truncate, /* truncate */ 7451566Smckusick fifo_update, /* update */ 7551566Smckusick fifo_bwrite, /* bwrite */ 7640292Smckusick }; 7740292Smckusick 7840292Smckusick /* 7940292Smckusick * Trivial lookup routine that always fails. 8040292Smckusick */ 8148014Smckusick /* ARGSUSED */ 82*52305Sheideman fifo_lookup(dvp, vpp, cnp) 83*52305Sheideman struct vnode *dvp; 84*52305Sheideman struct vnode **vpp; 85*52305Sheideman struct componentname *cnp; 8640292Smckusick { 87*52305Sheideman 88*52305Sheideman *vpp = NULL; 8940292Smckusick return (ENOTDIR); 9040292Smckusick } 9140292Smckusick 9240292Smckusick /* 9340292Smckusick * Open called to set up a new instance of a fifo or 9440292Smckusick * to find an active instance of a fifo. 9540292Smckusick */ 9640292Smckusick /* ARGSUSED */ 9748014Smckusick fifo_open(vp, mode, cred, p) 9840292Smckusick register struct vnode *vp; 9940292Smckusick int mode; 10040292Smckusick struct ucred *cred; 10148014Smckusick struct proc *p; 10240292Smckusick { 10340292Smckusick register struct fifoinfo *fip; 10440292Smckusick struct socket *rso, *wso; 10540292Smckusick int error; 10640637Skarels static char openstr[] = "fifo"; 10740292Smckusick 10840292Smckusick if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 10940292Smckusick return (EINVAL); 11040292Smckusick if ((fip = vp->v_fifoinfo) == NULL) { 11140292Smckusick MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 11240292Smckusick vp->v_fifoinfo = fip; 11340655Smckusick if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 11440655Smckusick free(fip, M_VNODE); 11540655Smckusick vp->v_fifoinfo = NULL; 11640292Smckusick return (error); 11740655Smckusick } 11840292Smckusick fip->fi_readsock = rso; 11940292Smckusick if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 12040292Smckusick (void)soclose(rso); 12140655Smckusick free(fip, M_VNODE); 12240655Smckusick vp->v_fifoinfo = NULL; 12340292Smckusick return (error); 12440292Smckusick } 12540292Smckusick fip->fi_writesock = wso; 12640292Smckusick if (error = unp_connect2(wso, rso)) { 12740292Smckusick (void)soclose(wso); 12840292Smckusick (void)soclose(rso); 12940655Smckusick free(fip, M_VNODE); 13040655Smckusick vp->v_fifoinfo = NULL; 13140292Smckusick return (error); 13240292Smckusick } 13340292Smckusick wso->so_state |= SS_CANTRCVMORE; 13440292Smckusick rso->so_state |= SS_CANTSENDMORE; 13540292Smckusick } 13640292Smckusick error = 0; 13740292Smckusick if (mode & FREAD) { 13840292Smckusick fip->fi_readers++; 13940292Smckusick if (fip->fi_readers == 1) { 14040292Smckusick fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 14140292Smckusick if (fip->fi_writers > 0) 14240292Smckusick wakeup((caddr_t)&fip->fi_writers); 14340292Smckusick } 14440292Smckusick if (mode & O_NONBLOCK) 14540292Smckusick return (0); 14640292Smckusick while (fip->fi_writers == 0) 14740637Skarels if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 14840637Skarels openstr, 0)) 14940292Smckusick break; 15040292Smckusick } else { 15140292Smckusick fip->fi_writers++; 15240292Smckusick if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 15340292Smckusick error = ENXIO; 15440292Smckusick } else { 15540292Smckusick if (fip->fi_writers == 1) { 15640292Smckusick fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 15740292Smckusick if (fip->fi_readers > 0) 15840292Smckusick wakeup((caddr_t)&fip->fi_readers); 15940292Smckusick } 16040292Smckusick while (fip->fi_readers == 0) 16140637Skarels if (error = tsleep((caddr_t)&fip->fi_writers, 16240637Skarels PSOCK, openstr, 0)) 16340292Smckusick break; 16440292Smckusick } 16540292Smckusick } 16640292Smckusick if (error) 16748014Smckusick fifo_close(vp, mode, cred, p); 16840292Smckusick return (error); 16940292Smckusick } 17040292Smckusick 17140292Smckusick /* 17240292Smckusick * Vnode op for read 17340292Smckusick */ 17440292Smckusick /* ARGSUSED */ 17540292Smckusick fifo_read(vp, uio, ioflag, cred) 17640292Smckusick struct vnode *vp; 17740292Smckusick register struct uio *uio; 17840292Smckusick int ioflag; 17940292Smckusick struct ucred *cred; 18040292Smckusick { 18140292Smckusick register struct socket *rso = vp->v_fifoinfo->fi_readsock; 18240292Smckusick int error, startresid; 18340292Smckusick 18448014Smckusick #ifdef DIAGNOSTIC 18540292Smckusick if (uio->uio_rw != UIO_READ) 18640292Smckusick panic("fifo_read mode"); 18748014Smckusick #endif 18840292Smckusick if (uio->uio_resid == 0) 18940292Smckusick return (0); 19040292Smckusick if (ioflag & IO_NDELAY) 19140292Smckusick rso->so_state |= SS_NBIO; 19240292Smckusick startresid = uio->uio_resid; 19340292Smckusick VOP_UNLOCK(vp); 19440292Smckusick error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 19540292Smckusick (struct mbuf **)0, (struct mbuf **)0); 19640292Smckusick VOP_LOCK(vp); 19740292Smckusick /* 19840292Smckusick * Clear EOF indication after first such return. 19940292Smckusick */ 20040292Smckusick if (uio->uio_resid == startresid) 20140292Smckusick rso->so_state &= ~SS_CANTRCVMORE; 20240292Smckusick if (ioflag & IO_NDELAY) 20340292Smckusick rso->so_state &= ~SS_NBIO; 20440292Smckusick return (error); 20540292Smckusick } 20640292Smckusick 20740292Smckusick /* 20840292Smckusick * Vnode op for write 20940292Smckusick */ 21040292Smckusick /* ARGSUSED */ 21140292Smckusick fifo_write(vp, uio, ioflag, cred) 21240292Smckusick struct vnode *vp; 21340292Smckusick register struct uio *uio; 21440292Smckusick int ioflag; 21540292Smckusick struct ucred *cred; 21640292Smckusick { 21740292Smckusick struct socket *wso = vp->v_fifoinfo->fi_writesock; 21840292Smckusick int error; 21940292Smckusick 22048014Smckusick #ifdef DIAGNOSTIC 22140292Smckusick if (uio->uio_rw != UIO_WRITE) 22240292Smckusick panic("fifo_write mode"); 22348014Smckusick #endif 22440292Smckusick if (ioflag & IO_NDELAY) 22540292Smckusick wso->so_state |= SS_NBIO; 22640292Smckusick VOP_UNLOCK(vp); 22740292Smckusick error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 22840292Smckusick VOP_LOCK(vp); 22940292Smckusick if (ioflag & IO_NDELAY) 23040292Smckusick wso->so_state &= ~SS_NBIO; 23140292Smckusick return (error); 23240292Smckusick } 23340292Smckusick 23440292Smckusick /* 23540292Smckusick * Device ioctl operation. 23640292Smckusick */ 23740292Smckusick /* ARGSUSED */ 23848014Smckusick fifo_ioctl(vp, com, data, fflag, cred, p) 23940292Smckusick struct vnode *vp; 24040292Smckusick int com; 24140292Smckusick caddr_t data; 24240292Smckusick int fflag; 24340292Smckusick struct ucred *cred; 24448014Smckusick struct proc *p; 24540292Smckusick { 24640292Smckusick struct file filetmp; 24740292Smckusick int error; 24840292Smckusick 24940292Smckusick if (com == FIONBIO) 25040292Smckusick return (0); 25140292Smckusick if (fflag & FREAD) 25240292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 25340292Smckusick else 25440292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 25548014Smckusick return (soo_ioctl(&filetmp, com, data, p)); 25640292Smckusick } 25740292Smckusick 25840292Smckusick /* ARGSUSED */ 25948014Smckusick fifo_select(vp, which, fflag, cred, p) 26040292Smckusick struct vnode *vp; 26140292Smckusick int which, fflag; 26240292Smckusick struct ucred *cred; 26348014Smckusick struct proc *p; 26440292Smckusick { 26540292Smckusick struct file filetmp; 26640292Smckusick int error; 26740292Smckusick 26840292Smckusick if (fflag & FREAD) 26940292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 27040292Smckusick else 27140292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 27248014Smckusick return (soo_select(&filetmp, which, p)); 27340292Smckusick } 27440292Smckusick 27540292Smckusick /* 27640292Smckusick * This is a noop, simply returning what one has been given. 27740292Smckusick */ 27840292Smckusick fifo_bmap(vp, bn, vpp, bnp) 27940292Smckusick struct vnode *vp; 28040292Smckusick daddr_t bn; 28140292Smckusick struct vnode **vpp; 28240292Smckusick daddr_t *bnp; 28340292Smckusick { 28440292Smckusick 28540292Smckusick if (vpp != NULL) 28640292Smckusick *vpp = vp; 28740292Smckusick if (bnp != NULL) 28840292Smckusick *bnp = bn; 28940292Smckusick return (0); 29040292Smckusick } 29140292Smckusick 29240292Smckusick /* 29340292Smckusick * At the moment we do not do any locking. 29440292Smckusick */ 29540292Smckusick /* ARGSUSED */ 29640292Smckusick fifo_lock(vp) 29740292Smckusick struct vnode *vp; 29840292Smckusick { 29940292Smckusick 30040292Smckusick return (0); 30140292Smckusick } 30240292Smckusick 30340292Smckusick /* ARGSUSED */ 30440292Smckusick fifo_unlock(vp) 30540292Smckusick struct vnode *vp; 30640292Smckusick { 30740292Smckusick 30840292Smckusick return (0); 30940292Smckusick } 31040292Smckusick 31140292Smckusick /* 31240292Smckusick * Device close routine 31340292Smckusick */ 31440292Smckusick /* ARGSUSED */ 31548014Smckusick fifo_close(vp, fflag, cred, p) 31640292Smckusick register struct vnode *vp; 31740292Smckusick int fflag; 31840292Smckusick struct ucred *cred; 31948014Smckusick struct proc *p; 32040292Smckusick { 32140292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 32240292Smckusick int error1, error2; 32340292Smckusick 32440292Smckusick if (fflag & FWRITE) { 32540292Smckusick fip->fi_writers--; 32640292Smckusick if (fip->fi_writers == 0) 32740292Smckusick socantrcvmore(fip->fi_readsock); 32840292Smckusick } else { 32940292Smckusick fip->fi_readers--; 33040292Smckusick if (fip->fi_readers == 0) 33140292Smckusick socantsendmore(fip->fi_writesock); 33240292Smckusick } 33340292Smckusick if (vp->v_usecount > 1) 33440292Smckusick return (0); 33540292Smckusick error1 = soclose(fip->fi_readsock); 33640292Smckusick error2 = soclose(fip->fi_writesock); 33740292Smckusick FREE(fip, M_VNODE); 33840292Smckusick vp->v_fifoinfo = NULL; 33940292Smckusick if (error1) 34040292Smckusick return (error1); 34140292Smckusick return (error2); 34240292Smckusick } 34340292Smckusick 34440292Smckusick /* 34540292Smckusick * Print out the contents of a fifo vnode. 34640292Smckusick */ 34740292Smckusick fifo_print(vp) 34840292Smckusick struct vnode *vp; 34940292Smckusick { 35040292Smckusick 35140292Smckusick printf("tag VT_NON"); 35240292Smckusick fifo_printinfo(vp); 35340292Smckusick printf("\n"); 35440292Smckusick } 35540292Smckusick 35640292Smckusick /* 35740292Smckusick * Print out internal contents of a fifo vnode. 35840292Smckusick */ 35940292Smckusick fifo_printinfo(vp) 36040292Smckusick struct vnode *vp; 36140292Smckusick { 36240292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 36340292Smckusick 36440292Smckusick printf(", fifo with %d readers and %d writers", 36540292Smckusick fip->fi_readers, fip->fi_writers); 36640292Smckusick } 36740292Smckusick 36840292Smckusick /* 36940292Smckusick * Fifo failed operation 37040292Smckusick */ 37140292Smckusick fifo_ebadf() 37240292Smckusick { 37340292Smckusick 37440292Smckusick return (EBADF); 37540292Smckusick } 37640292Smckusick 37740292Smckusick /* 37846198Smckusick * Fifo advisory byte-level locks. 37946198Smckusick */ 38048014Smckusick /* ARGSUSED */ 38146198Smckusick fifo_advlock(vp, id, op, fl, flags) 38246198Smckusick struct vnode *vp; 38346198Smckusick caddr_t id; 38446198Smckusick int op; 38546198Smckusick struct flock *fl; 38646198Smckusick int flags; 38746198Smckusick { 38846198Smckusick 38946198Smckusick return (EOPNOTSUPP); 39046198Smckusick } 39146198Smckusick 39246198Smckusick /* 39340292Smckusick * Fifo bad operation 39440292Smckusick */ 39540292Smckusick fifo_badop() 39640292Smckusick { 39740292Smckusick 39840292Smckusick panic("fifo_badop called"); 39940292Smckusick /* NOTREACHED */ 40040292Smckusick } 401