140292Smckusick /* 240292Smckusick * Copyright (c) 1990 The Regents of the University of California. 340292Smckusick * All rights reserved. 440292Smckusick * 544430Sbostic * %sccs.include.redist.c% 640292Smckusick * 7*53537Sheideman * @(#)fifo_vnops.c 7.13 (Berkeley) 05/14/92 840292Smckusick */ 940292Smckusick 1040292Smckusick #include "param.h" 1152512Smckusick #include "proc.h" 1240292Smckusick #include "time.h" 1340292Smckusick #include "namei.h" 1440292Smckusick #include "vnode.h" 1540292Smckusick #include "socket.h" 1640292Smckusick #include "socketvar.h" 1740292Smckusick #include "stat.h" 1847540Skarels #include "systm.h" 1940292Smckusick #include "ioctl.h" 2040292Smckusick #include "file.h" 2148014Smckusick #include "fifo.h" 2240292Smckusick #include "errno.h" 2340292Smckusick #include "malloc.h" 2440292Smckusick 2540292Smckusick /* 2640292Smckusick * This structure is associated with the FIFO vnode and stores 2740292Smckusick * the state associated with the FIFO. 2840292Smckusick */ 2940292Smckusick struct fifoinfo { 3040292Smckusick struct socket *fi_readsock; 3140292Smckusick struct socket *fi_writesock; 3240292Smckusick long fi_readers; 3340292Smckusick long fi_writers; 3440292Smckusick }; 3540292Smckusick 36*53537Sheideman int (**fifo_vnodeop_p)(); 37*53537Sheideman struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 38*53537Sheideman { &vop_default_desc, vn_default_error }, 39*53537Sheideman { &vop_lookup_desc, fifo_lookup }, /* lookup */ 40*53537Sheideman { &vop_create_desc, fifo_create }, /* create */ 41*53537Sheideman { &vop_mknod_desc, fifo_mknod }, /* mknod */ 42*53537Sheideman { &vop_open_desc, fifo_open }, /* open */ 43*53537Sheideman { &vop_close_desc, fifo_close }, /* close */ 44*53537Sheideman { &vop_access_desc, fifo_access }, /* access */ 45*53537Sheideman { &vop_getattr_desc, fifo_getattr }, /* getattr */ 46*53537Sheideman { &vop_setattr_desc, fifo_setattr }, /* setattr */ 47*53537Sheideman { &vop_read_desc, fifo_read }, /* read */ 48*53537Sheideman { &vop_write_desc, fifo_write }, /* write */ 49*53537Sheideman { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 50*53537Sheideman { &vop_select_desc, fifo_select }, /* select */ 51*53537Sheideman { &vop_mmap_desc, fifo_mmap }, /* mmap */ 52*53537Sheideman { &vop_fsync_desc, fifo_fsync }, /* fsync */ 53*53537Sheideman { &vop_seek_desc, fifo_seek }, /* seek */ 54*53537Sheideman { &vop_remove_desc, fifo_remove }, /* remove */ 55*53537Sheideman { &vop_link_desc, fifo_link }, /* link */ 56*53537Sheideman { &vop_rename_desc, fifo_rename }, /* rename */ 57*53537Sheideman { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 58*53537Sheideman { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 59*53537Sheideman { &vop_symlink_desc, fifo_symlink }, /* symlink */ 60*53537Sheideman { &vop_readdir_desc, fifo_readdir }, /* readdir */ 61*53537Sheideman { &vop_readlink_desc, fifo_readlink }, /* readlink */ 62*53537Sheideman { &vop_abortop_desc, fifo_abortop }, /* abortop */ 63*53537Sheideman { &vop_inactive_desc, fifo_inactive }, /* inactive */ 64*53537Sheideman { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */ 65*53537Sheideman { &vop_lock_desc, fifo_lock }, /* lock */ 66*53537Sheideman { &vop_unlock_desc, fifo_unlock }, /* unlock */ 67*53537Sheideman { &vop_bmap_desc, fifo_bmap }, /* bmap */ 68*53537Sheideman { &vop_strategy_desc, fifo_strategy }, /* strategy */ 69*53537Sheideman { &vop_print_desc, fifo_print }, /* print */ 70*53537Sheideman { &vop_islocked_desc, fifo_islocked }, /* islocked */ 71*53537Sheideman { &vop_advlock_desc, fifo_advlock }, /* advlock */ 72*53537Sheideman { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 73*53537Sheideman { &vop_vget_desc, fifo_vget }, /* vget */ 74*53537Sheideman { &vop_valloc_desc, fifo_valloc }, /* valloc */ 75*53537Sheideman { &vop_vfree_desc, fifo_vfree }, /* vfree */ 76*53537Sheideman { &vop_truncate_desc, fifo_truncate }, /* truncate */ 77*53537Sheideman { &vop_update_desc, fifo_update }, /* update */ 78*53537Sheideman { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ 79*53537Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 8040292Smckusick }; 81*53537Sheideman struct vnodeopv_desc fifo_vnodeop_opv_desc = 82*53537Sheideman { &fifo_vnodeop_p, fifo_vnodeop_entries }; 8340292Smckusick 8440292Smckusick /* 8540292Smckusick * Trivial lookup routine that always fails. 8640292Smckusick */ 8748014Smckusick /* ARGSUSED */ 88*53537Sheideman fifo_lookup (ap) 89*53537Sheideman struct vop_lookup_args *ap; 90*53537Sheideman #define dvp (ap->a_dvp) 91*53537Sheideman #define vpp (ap->a_vpp) 92*53537Sheideman #define cnp (ap->a_cnp) 9340292Smckusick { 9452305Sheideman 9552305Sheideman *vpp = NULL; 9640292Smckusick return (ENOTDIR); 9740292Smckusick } 98*53537Sheideman #undef dvp 99*53537Sheideman #undef vpp 100*53537Sheideman #undef cnp 10140292Smckusick 10240292Smckusick /* 10340292Smckusick * Open called to set up a new instance of a fifo or 10440292Smckusick * to find an active instance of a fifo. 10540292Smckusick */ 10640292Smckusick /* ARGSUSED */ 107*53537Sheideman fifo_open (ap) 108*53537Sheideman struct vop_open_args *ap; 109*53537Sheideman #define vp (ap->a_vp) 110*53537Sheideman #define mode (ap->a_mode) 111*53537Sheideman #define cred (ap->a_cred) 112*53537Sheideman #define p (ap->a_p) 11340292Smckusick { 114*53537Sheideman USES_VOP_CLOSE; 115*53537Sheideman USES_VOP_LOCK; 116*53537Sheideman USES_VOP_UNLOCK; 11740292Smckusick register struct fifoinfo *fip; 11840292Smckusick struct socket *rso, *wso; 11940292Smckusick int error; 12040637Skarels static char openstr[] = "fifo"; 12140292Smckusick 12240292Smckusick if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 12340292Smckusick return (EINVAL); 12440292Smckusick if ((fip = vp->v_fifoinfo) == NULL) { 12540292Smckusick MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 12640292Smckusick vp->v_fifoinfo = fip; 12740655Smckusick if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 12840655Smckusick free(fip, M_VNODE); 12940655Smckusick vp->v_fifoinfo = NULL; 13040292Smckusick return (error); 13140655Smckusick } 13240292Smckusick fip->fi_readsock = rso; 13340292Smckusick if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 13440292Smckusick (void)soclose(rso); 13540655Smckusick free(fip, M_VNODE); 13640655Smckusick vp->v_fifoinfo = NULL; 13740292Smckusick return (error); 13840292Smckusick } 13940292Smckusick fip->fi_writesock = wso; 14040292Smckusick if (error = unp_connect2(wso, rso)) { 14140292Smckusick (void)soclose(wso); 14240292Smckusick (void)soclose(rso); 14340655Smckusick free(fip, M_VNODE); 14440655Smckusick vp->v_fifoinfo = NULL; 14540292Smckusick return (error); 14640292Smckusick } 14753147Smckusick fip->fi_readers = fip->fi_writers = 0; 14840292Smckusick wso->so_state |= SS_CANTRCVMORE; 14940292Smckusick rso->so_state |= SS_CANTSENDMORE; 15040292Smckusick } 15140292Smckusick error = 0; 15240292Smckusick if (mode & FREAD) { 15340292Smckusick fip->fi_readers++; 15440292Smckusick if (fip->fi_readers == 1) { 15540292Smckusick fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 15640292Smckusick if (fip->fi_writers > 0) 15740292Smckusick wakeup((caddr_t)&fip->fi_writers); 15840292Smckusick } 15940292Smckusick if (mode & O_NONBLOCK) 16040292Smckusick return (0); 16153147Smckusick while (fip->fi_writers == 0) { 16253147Smckusick VOP_UNLOCK(vp); 16353147Smckusick error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 16453147Smckusick openstr, 0); 16553147Smckusick VOP_LOCK(vp); 16653147Smckusick if (error) 16740292Smckusick break; 16853147Smckusick } 16940292Smckusick } else { 17040292Smckusick fip->fi_writers++; 17140292Smckusick if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 17240292Smckusick error = ENXIO; 17340292Smckusick } else { 17440292Smckusick if (fip->fi_writers == 1) { 17540292Smckusick fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 17640292Smckusick if (fip->fi_readers > 0) 17740292Smckusick wakeup((caddr_t)&fip->fi_readers); 17840292Smckusick } 17953147Smckusick while (fip->fi_readers == 0) { 18053147Smckusick VOP_UNLOCK(vp); 18153147Smckusick error = tsleep((caddr_t)&fip->fi_writers, 18253147Smckusick PSOCK, openstr, 0); 18353147Smckusick VOP_LOCK(vp); 18453147Smckusick if (error) 18540292Smckusick break; 18653147Smckusick } 18740292Smckusick } 18840292Smckusick } 18940292Smckusick if (error) 190*53537Sheideman VOP_CLOSE(vp, mode, cred, p); 19140292Smckusick return (error); 19240292Smckusick } 193*53537Sheideman #undef vp 194*53537Sheideman #undef mode 195*53537Sheideman #undef cred 196*53537Sheideman #undef p 19740292Smckusick 19840292Smckusick /* 19940292Smckusick * Vnode op for read 20040292Smckusick */ 20140292Smckusick /* ARGSUSED */ 202*53537Sheideman fifo_read (ap) 203*53537Sheideman struct vop_read_args *ap; 204*53537Sheideman #define vp (ap->a_vp) 205*53537Sheideman #define uio (ap->a_uio) 206*53537Sheideman #define ioflag (ap->a_ioflag) 207*53537Sheideman #define cred (ap->a_cred) 20840292Smckusick { 209*53537Sheideman USES_VOP_LOCK; 210*53537Sheideman USES_VOP_UNLOCK; 21140292Smckusick register struct socket *rso = vp->v_fifoinfo->fi_readsock; 21240292Smckusick int error, startresid; 21340292Smckusick 21448014Smckusick #ifdef DIAGNOSTIC 21540292Smckusick if (uio->uio_rw != UIO_READ) 21640292Smckusick panic("fifo_read mode"); 21748014Smckusick #endif 21840292Smckusick if (uio->uio_resid == 0) 21940292Smckusick return (0); 22040292Smckusick if (ioflag & IO_NDELAY) 22140292Smckusick rso->so_state |= SS_NBIO; 22240292Smckusick startresid = uio->uio_resid; 22340292Smckusick VOP_UNLOCK(vp); 22440292Smckusick error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 22540292Smckusick (struct mbuf **)0, (struct mbuf **)0); 22640292Smckusick VOP_LOCK(vp); 22740292Smckusick /* 22840292Smckusick * Clear EOF indication after first such return. 22940292Smckusick */ 23040292Smckusick if (uio->uio_resid == startresid) 23140292Smckusick rso->so_state &= ~SS_CANTRCVMORE; 23240292Smckusick if (ioflag & IO_NDELAY) 23340292Smckusick rso->so_state &= ~SS_NBIO; 23440292Smckusick return (error); 23540292Smckusick } 236*53537Sheideman #undef vp 237*53537Sheideman #undef uio 238*53537Sheideman #undef ioflag 239*53537Sheideman #undef cred 24040292Smckusick 24140292Smckusick /* 24240292Smckusick * Vnode op for write 24340292Smckusick */ 24440292Smckusick /* ARGSUSED */ 245*53537Sheideman fifo_write (ap) 246*53537Sheideman struct vop_write_args *ap; 247*53537Sheideman #define vp (ap->a_vp) 248*53537Sheideman #define uio (ap->a_uio) 249*53537Sheideman #define ioflag (ap->a_ioflag) 250*53537Sheideman #define cred (ap->a_cred) 25140292Smckusick { 252*53537Sheideman USES_VOP_LOCK; 253*53537Sheideman USES_VOP_UNLOCK; 25440292Smckusick struct socket *wso = vp->v_fifoinfo->fi_writesock; 25540292Smckusick int error; 25640292Smckusick 25748014Smckusick #ifdef DIAGNOSTIC 25840292Smckusick if (uio->uio_rw != UIO_WRITE) 25940292Smckusick panic("fifo_write mode"); 26048014Smckusick #endif 26140292Smckusick if (ioflag & IO_NDELAY) 26240292Smckusick wso->so_state |= SS_NBIO; 26340292Smckusick VOP_UNLOCK(vp); 26453423Smckusick error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0, 0); 26540292Smckusick VOP_LOCK(vp); 26640292Smckusick if (ioflag & IO_NDELAY) 26740292Smckusick wso->so_state &= ~SS_NBIO; 26840292Smckusick return (error); 26940292Smckusick } 270*53537Sheideman #undef vp 271*53537Sheideman #undef uio 272*53537Sheideman #undef ioflag 273*53537Sheideman #undef cred 27440292Smckusick 27540292Smckusick /* 27640292Smckusick * Device ioctl operation. 27740292Smckusick */ 27840292Smckusick /* ARGSUSED */ 279*53537Sheideman fifo_ioctl (ap) 280*53537Sheideman struct vop_ioctl_args *ap; 281*53537Sheideman #define vp (ap->a_vp) 282*53537Sheideman #define com (ap->a_command) 283*53537Sheideman #define data (ap->a_data) 284*53537Sheideman #define fflag (ap->a_fflag) 285*53537Sheideman #define cred (ap->a_cred) 286*53537Sheideman #define p (ap->a_p) 28740292Smckusick { 28840292Smckusick struct file filetmp; 28940292Smckusick int error; 29040292Smckusick 29140292Smckusick if (com == FIONBIO) 29240292Smckusick return (0); 29340292Smckusick if (fflag & FREAD) 29440292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 29540292Smckusick else 29640292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 29748014Smckusick return (soo_ioctl(&filetmp, com, data, p)); 29840292Smckusick } 299*53537Sheideman #undef vp 300*53537Sheideman #undef com 301*53537Sheideman #undef data 302*53537Sheideman #undef fflag 303*53537Sheideman #undef cred 304*53537Sheideman #undef p 30540292Smckusick 30640292Smckusick /* ARGSUSED */ 307*53537Sheideman fifo_select (ap) 308*53537Sheideman struct vop_select_args *ap; 309*53537Sheideman #define vp (ap->a_vp) 310*53537Sheideman #define which (ap->a_which) 311*53537Sheideman #define fflag (ap->a_fflags) 312*53537Sheideman #define cred (ap->a_cred) 313*53537Sheideman #define p (ap->a_p) 31440292Smckusick { 31540292Smckusick struct file filetmp; 31640292Smckusick int error; 31740292Smckusick 31840292Smckusick if (fflag & FREAD) 31940292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 32040292Smckusick else 32140292Smckusick filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 32248014Smckusick return (soo_select(&filetmp, which, p)); 32340292Smckusick } 324*53537Sheideman #undef vp 325*53537Sheideman #undef which 326*53537Sheideman #undef fflag 327*53537Sheideman #undef cred 328*53537Sheideman #undef p 32940292Smckusick 33040292Smckusick /* 33140292Smckusick * This is a noop, simply returning what one has been given. 33240292Smckusick */ 333*53537Sheideman fifo_bmap (ap) 334*53537Sheideman struct vop_bmap_args *ap; 335*53537Sheideman #define vp (ap->a_vp) 336*53537Sheideman #define bn (ap->a_bn) 337*53537Sheideman #define vpp (ap->a_vpp) 338*53537Sheideman #define bnp (ap->a_bnp) 33940292Smckusick { 34040292Smckusick 34140292Smckusick if (vpp != NULL) 34240292Smckusick *vpp = vp; 34340292Smckusick if (bnp != NULL) 34440292Smckusick *bnp = bn; 34540292Smckusick return (0); 34640292Smckusick } 347*53537Sheideman #undef vp 348*53537Sheideman #undef bn 349*53537Sheideman #undef vpp 350*53537Sheideman #undef bnp 35140292Smckusick 35240292Smckusick /* 35340292Smckusick * At the moment we do not do any locking. 35440292Smckusick */ 35540292Smckusick /* ARGSUSED */ 356*53537Sheideman fifo_lock (ap) 357*53537Sheideman struct vop_lock_args *ap; 358*53537Sheideman #define vp (ap->a_vp) 35940292Smckusick { 36040292Smckusick 36140292Smckusick return (0); 36240292Smckusick } 363*53537Sheideman #undef vp 36440292Smckusick 36540292Smckusick /* ARGSUSED */ 366*53537Sheideman fifo_unlock (ap) 367*53537Sheideman struct vop_unlock_args *ap; 368*53537Sheideman #define vp (ap->a_vp) 36940292Smckusick { 37040292Smckusick 37140292Smckusick return (0); 37240292Smckusick } 373*53537Sheideman #undef vp 37440292Smckusick 37540292Smckusick /* 37640292Smckusick * Device close routine 37740292Smckusick */ 37840292Smckusick /* ARGSUSED */ 379*53537Sheideman fifo_close (ap) 380*53537Sheideman struct vop_close_args *ap; 381*53537Sheideman #define vp (ap->a_vp) 382*53537Sheideman #define fflag (ap->a_fflag) 383*53537Sheideman #define cred (ap->a_cred) 384*53537Sheideman #define p (ap->a_p) 38540292Smckusick { 38640292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 38740292Smckusick int error1, error2; 38840292Smckusick 38940292Smckusick if (fflag & FWRITE) { 39040292Smckusick fip->fi_writers--; 39140292Smckusick if (fip->fi_writers == 0) 39240292Smckusick socantrcvmore(fip->fi_readsock); 39340292Smckusick } else { 39440292Smckusick fip->fi_readers--; 39540292Smckusick if (fip->fi_readers == 0) 39640292Smckusick socantsendmore(fip->fi_writesock); 39740292Smckusick } 39840292Smckusick if (vp->v_usecount > 1) 39940292Smckusick return (0); 40040292Smckusick error1 = soclose(fip->fi_readsock); 40140292Smckusick error2 = soclose(fip->fi_writesock); 40240292Smckusick FREE(fip, M_VNODE); 40340292Smckusick vp->v_fifoinfo = NULL; 40440292Smckusick if (error1) 40540292Smckusick return (error1); 40640292Smckusick return (error2); 40740292Smckusick } 408*53537Sheideman #undef vp 409*53537Sheideman #undef fflag 410*53537Sheideman #undef cred 411*53537Sheideman #undef p 41240292Smckusick 41340292Smckusick /* 41440292Smckusick * Print out the contents of a fifo vnode. 41540292Smckusick */ 416*53537Sheideman fifo_print (ap) 417*53537Sheideman struct vop_print_args *ap; 418*53537Sheideman #define vp (ap->a_vp) 41940292Smckusick { 42040292Smckusick 42140292Smckusick printf("tag VT_NON"); 42240292Smckusick fifo_printinfo(vp); 42340292Smckusick printf("\n"); 42440292Smckusick } 425*53537Sheideman #undef vp 42640292Smckusick 42740292Smckusick /* 42840292Smckusick * Print out internal contents of a fifo vnode. 42940292Smckusick */ 43040292Smckusick fifo_printinfo(vp) 43140292Smckusick struct vnode *vp; 43240292Smckusick { 43340292Smckusick register struct fifoinfo *fip = vp->v_fifoinfo; 43440292Smckusick 43540292Smckusick printf(", fifo with %d readers and %d writers", 43640292Smckusick fip->fi_readers, fip->fi_writers); 43740292Smckusick } 43840292Smckusick 43940292Smckusick /* 44040292Smckusick * Fifo failed operation 44140292Smckusick */ 44240292Smckusick fifo_ebadf() 44340292Smckusick { 44440292Smckusick 44540292Smckusick return (EBADF); 44640292Smckusick } 44740292Smckusick 44840292Smckusick /* 44946198Smckusick * Fifo advisory byte-level locks. 45046198Smckusick */ 45148014Smckusick /* ARGSUSED */ 452*53537Sheideman fifo_advlock (ap) 453*53537Sheideman struct vop_advlock_args *ap; 454*53537Sheideman #define vp (ap->a_vp) 455*53537Sheideman #define id (ap->a_id) 456*53537Sheideman #define op (ap->a_op) 457*53537Sheideman #define fl (ap->a_fl) 458*53537Sheideman #define flags (ap->a_flags) 45946198Smckusick { 46046198Smckusick 46146198Smckusick return (EOPNOTSUPP); 46246198Smckusick } 463*53537Sheideman #undef vp 464*53537Sheideman #undef id 465*53537Sheideman #undef op 466*53537Sheideman #undef fl 467*53537Sheideman #undef flags 46846198Smckusick 46946198Smckusick /* 47040292Smckusick * Fifo bad operation 47140292Smckusick */ 47240292Smckusick fifo_badop() 47340292Smckusick { 47440292Smckusick 47540292Smckusick panic("fifo_badop called"); 47640292Smckusick /* NOTREACHED */ 47740292Smckusick } 478