123398Smckusick /* 263181Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363181Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 923398Smckusick * 1044460Sbostic * %sccs.include.redist.c% 1137731Smckusick * 12*69737Smckusick * @(#)vfs_vnops.c 8.13 (Berkeley) 05/27/95 1323398Smckusick */ 1418Sbill 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/kernel.h> 1856517Sbostic #include <sys/file.h> 1956517Sbostic #include <sys/stat.h> 2056517Sbostic #include <sys/buf.h> 2156517Sbostic #include <sys/proc.h> 2256517Sbostic #include <sys/mount.h> 2356517Sbostic #include <sys/namei.h> 2456517Sbostic #include <sys/vnode.h> 2556517Sbostic #include <sys/ioctl.h> 2656517Sbostic #include <sys/tty.h> 2756517Sbostic 2853469Smckusick #include <vm/vm.h> 2918Sbill 3037731Smckusick struct fileops vnops = 3150164Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; 3237520Smckusick 3318Sbill /* 3437731Smckusick * Common code for vnode open operations. 3537731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 3618Sbill */ 3752310Smckusick vn_open(ndp, fmode, cmode) 3837731Smckusick register struct nameidata *ndp; 3937731Smckusick int fmode, cmode; 4037731Smckusick { 4137731Smckusick register struct vnode *vp; 4252310Smckusick register struct proc *p = ndp->ni_cnd.cn_proc; 4352331Smckusick register struct ucred *cred = p->p_ucred; 4437731Smckusick struct vattr vat; 4537731Smckusick struct vattr *vap = &vat; 4637731Smckusick int error; 4737731Smckusick 4849943Smckusick if (fmode & O_CREAT) { 4952310Smckusick ndp->ni_cnd.cn_nameiop = CREATE; 5052310Smckusick ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 5149943Smckusick if ((fmode & O_EXCL) == 0) 5252310Smckusick ndp->ni_cnd.cn_flags |= FOLLOW; 5352310Smckusick if (error = namei(ndp)) 5437731Smckusick return (error); 5537731Smckusick if (ndp->ni_vp == NULL) { 5641362Smckusick VATTR_NULL(vap); 5737731Smckusick vap->va_type = VREG; 5837731Smckusick vap->va_mode = cmode; 5968578Smckusick if (fmode & O_EXCL) 6068578Smckusick vap->va_vaflags |= VA_EXCLUSIVE; 6167655Smckusick VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE); 6252310Smckusick if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 6352310Smckusick &ndp->ni_cnd, vap)) 6437731Smckusick return (error); 6549943Smckusick fmode &= ~O_TRUNC; 6637731Smckusick vp = ndp->ni_vp; 6737731Smckusick } else { 6852230Sheideman VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 6939761Smckusick if (ndp->ni_dvp == ndp->ni_vp) 7039761Smckusick vrele(ndp->ni_dvp); 7143343Smckusick else 7239761Smckusick vput(ndp->ni_dvp); 7339761Smckusick ndp->ni_dvp = NULL; 7437731Smckusick vp = ndp->ni_vp; 7549943Smckusick if (fmode & O_EXCL) { 7637731Smckusick error = EEXIST; 7737731Smckusick goto bad; 7837731Smckusick } 7949943Smckusick fmode &= ~O_CREAT; 8037731Smckusick } 8137731Smckusick } else { 8252310Smckusick ndp->ni_cnd.cn_nameiop = LOOKUP; 8352310Smckusick ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF; 8452310Smckusick if (error = namei(ndp)) 8537731Smckusick return (error); 8637731Smckusick vp = ndp->ni_vp; 8737731Smckusick } 8837731Smckusick if (vp->v_type == VSOCK) { 8937731Smckusick error = EOPNOTSUPP; 9037731Smckusick goto bad; 9137731Smckusick } 9249943Smckusick if ((fmode & O_CREAT) == 0) { 9337731Smckusick if (fmode & FREAD) { 9448030Smckusick if (error = VOP_ACCESS(vp, VREAD, cred, p)) 9537731Smckusick goto bad; 9637731Smckusick } 9749943Smckusick if (fmode & (FWRITE | O_TRUNC)) { 9837731Smckusick if (vp->v_type == VDIR) { 9937731Smckusick error = EISDIR; 10037731Smckusick goto bad; 10137731Smckusick } 10238401Smckusick if ((error = vn_writechk(vp)) || 10348030Smckusick (error = VOP_ACCESS(vp, VWRITE, cred, p))) 10438401Smckusick goto bad; 10537731Smckusick } 10637731Smckusick } 10749943Smckusick if (fmode & O_TRUNC) { 10869407Smckusick VOP_UNLOCK(vp, 0, p); /* XXX */ 10967655Smckusick VOP_LEASE(vp, p, cred, LEASE_WRITE); 11069407Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ 11141362Smckusick VATTR_NULL(vap); 11237731Smckusick vap->va_size = 0; 11348030Smckusick if (error = VOP_SETATTR(vp, vap, cred, p)) 11437731Smckusick goto bad; 11537731Smckusick } 11650110Smckusick if (error = VOP_OPEN(vp, fmode, cred, p)) 11750110Smckusick goto bad; 11850110Smckusick if (fmode & FWRITE) 11950110Smckusick vp->v_writecount++; 12050110Smckusick return (0); 12137731Smckusick bad: 12237731Smckusick vput(vp); 12340707Skarels return (error); 12437731Smckusick } 12537731Smckusick 12637731Smckusick /* 12738401Smckusick * Check for write permissions on the specified vnode. 128*69737Smckusick * Prototype text segments cannot be written. 12937731Smckusick */ 13038401Smckusick vn_writechk(vp) 13137731Smckusick register struct vnode *vp; 13218Sbill { 13318Sbill 13438401Smckusick /* 13538401Smckusick * If there's shared text associated with 13638401Smckusick * the vnode, try to free it up once. If 13738401Smckusick * we fail, we can't allow writing. 13838401Smckusick */ 13945744Smckusick if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) 14038401Smckusick return (ETXTBSY); 14138401Smckusick return (0); 14237731Smckusick } 14337731Smckusick 14437731Smckusick /* 14550164Smckusick * Vnode close call 14637731Smckusick */ 14750164Smckusick vn_close(vp, flags, cred, p) 14850164Smckusick register struct vnode *vp; 14950164Smckusick int flags; 15050164Smckusick struct ucred *cred; 15150164Smckusick struct proc *p; 15250164Smckusick { 15350164Smckusick int error; 15450164Smckusick 15550164Smckusick if (flags & FWRITE) 15650164Smckusick vp->v_writecount--; 15750164Smckusick error = VOP_CLOSE(vp, flags, cred, p); 15850164Smckusick vrele(vp); 15950164Smckusick return (error); 16050164Smckusick } 16150164Smckusick 16250164Smckusick /* 16350164Smckusick * Package up an I/O request on a vnode into a uio and do it. 16450164Smckusick */ 16548030Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 16637731Smckusick enum uio_rw rw; 16737731Smckusick struct vnode *vp; 16837731Smckusick caddr_t base; 16937731Smckusick int len; 17037731Smckusick off_t offset; 17137731Smckusick enum uio_seg segflg; 17237731Smckusick int ioflg; 17337731Smckusick struct ucred *cred; 17437731Smckusick int *aresid; 17548030Smckusick struct proc *p; 17637731Smckusick { 17737731Smckusick struct uio auio; 17837731Smckusick struct iovec aiov; 17937731Smckusick int error; 18037731Smckusick 18139590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 18269407Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 18337731Smckusick auio.uio_iov = &aiov; 18437731Smckusick auio.uio_iovcnt = 1; 18537731Smckusick aiov.iov_base = base; 18637731Smckusick aiov.iov_len = len; 18737731Smckusick auio.uio_resid = len; 18837731Smckusick auio.uio_offset = offset; 18937731Smckusick auio.uio_segflg = segflg; 19037731Smckusick auio.uio_rw = rw; 19148030Smckusick auio.uio_procp = p; 19252191Smckusick if (rw == UIO_READ) { 19339590Smckusick error = VOP_READ(vp, &auio, ioflg, cred); 19452191Smckusick } else { 19539590Smckusick error = VOP_WRITE(vp, &auio, ioflg, cred); 19652191Smckusick } 19737731Smckusick if (aresid) 19837731Smckusick *aresid = auio.uio_resid; 19937731Smckusick else 20037731Smckusick if (auio.uio_resid && error == 0) 20137731Smckusick error = EIO; 20239590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 20369407Smckusick VOP_UNLOCK(vp, 0, p); 20437731Smckusick return (error); 20537731Smckusick } 20637731Smckusick 20750164Smckusick /* 20850164Smckusick * File table vnode read routine. 20950164Smckusick */ 21037731Smckusick vn_read(fp, uio, cred) 21137731Smckusick struct file *fp; 21237731Smckusick struct uio *uio; 21337731Smckusick struct ucred *cred; 21437731Smckusick { 21569407Smckusick struct vnode *vp = (struct vnode *)fp->f_data; 21669407Smckusick struct proc *p = uio->uio_procp; 21739590Smckusick int count, error; 21837731Smckusick 21969407Smckusick VOP_LEASE(vp, p, cred, LEASE_READ); 22069407Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 22139590Smckusick uio->uio_offset = fp->f_offset; 22239590Smckusick count = uio->uio_resid; 22349943Smckusick error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, 22449943Smckusick cred); 22539590Smckusick fp->f_offset += count - uio->uio_resid; 22669407Smckusick VOP_UNLOCK(vp, 0, p); 22739590Smckusick return (error); 22837731Smckusick } 22937731Smckusick 23050164Smckusick /* 23150164Smckusick * File table vnode write routine. 23250164Smckusick */ 23337731Smckusick vn_write(fp, uio, cred) 23437731Smckusick struct file *fp; 23537731Smckusick struct uio *uio; 23637731Smckusick struct ucred *cred; 23737731Smckusick { 23869407Smckusick struct vnode *vp = (struct vnode *)fp->f_data; 23969407Smckusick struct proc *p = uio->uio_procp; 24068064Smckusick int count, error, ioflag = IO_UNIT; 24137731Smckusick 24249943Smckusick if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 24337731Smckusick ioflag |= IO_APPEND; 24449943Smckusick if (fp->f_flag & FNONBLOCK) 24537731Smckusick ioflag |= IO_NDELAY; 24668725Smckusick if ((fp->f_flag & O_FSYNC) || (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)) 24768712Smckusick ioflag |= IO_SYNC; 24869407Smckusick VOP_LEASE(vp, p, cred, LEASE_WRITE); 24969407Smckusick vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 25039590Smckusick uio->uio_offset = fp->f_offset; 25139590Smckusick count = uio->uio_resid; 25239590Smckusick error = VOP_WRITE(vp, uio, ioflag, cred); 25339590Smckusick if (ioflag & IO_APPEND) 25439590Smckusick fp->f_offset = uio->uio_offset; 25539590Smckusick else 25639590Smckusick fp->f_offset += count - uio->uio_resid; 25769407Smckusick VOP_UNLOCK(vp, 0, p); 25839590Smckusick return (error); 25937731Smckusick } 26037731Smckusick 26137731Smckusick /* 26250164Smckusick * File table vnode stat routine. 26337731Smckusick */ 26448030Smckusick vn_stat(vp, sb, p) 26537731Smckusick struct vnode *vp; 26637731Smckusick register struct stat *sb; 26748030Smckusick struct proc *p; 26837731Smckusick { 26937731Smckusick struct vattr vattr; 27037731Smckusick register struct vattr *vap; 27137731Smckusick int error; 27237731Smckusick u_short mode; 27337731Smckusick 27437731Smckusick vap = &vattr; 27548030Smckusick error = VOP_GETATTR(vp, vap, p->p_ucred, p); 27637731Smckusick if (error) 27737731Smckusick return (error); 27837731Smckusick /* 27937731Smckusick * Copy from vattr table 28037731Smckusick */ 28137731Smckusick sb->st_dev = vap->va_fsid; 28237731Smckusick sb->st_ino = vap->va_fileid; 28337731Smckusick mode = vap->va_mode; 28437731Smckusick switch (vp->v_type) { 28537731Smckusick case VREG: 28639382Smckusick mode |= S_IFREG; 28737731Smckusick break; 28837731Smckusick case VDIR: 28939382Smckusick mode |= S_IFDIR; 29037731Smckusick break; 29137731Smckusick case VBLK: 29239382Smckusick mode |= S_IFBLK; 29337731Smckusick break; 29437731Smckusick case VCHR: 29539382Smckusick mode |= S_IFCHR; 29637731Smckusick break; 29737731Smckusick case VLNK: 29839382Smckusick mode |= S_IFLNK; 29937731Smckusick break; 30037731Smckusick case VSOCK: 30139382Smckusick mode |= S_IFSOCK; 30237731Smckusick break; 30340284Smckusick case VFIFO: 30440284Smckusick mode |= S_IFIFO; 30540284Smckusick break; 30637731Smckusick default: 30737731Smckusick return (EBADF); 30837731Smckusick }; 30937731Smckusick sb->st_mode = mode; 31037731Smckusick sb->st_nlink = vap->va_nlink; 31137731Smckusick sb->st_uid = vap->va_uid; 31237731Smckusick sb->st_gid = vap->va_gid; 31337731Smckusick sb->st_rdev = vap->va_rdev; 31437731Smckusick sb->st_size = vap->va_size; 31554100Smckusick sb->st_atimespec = vap->va_atime; 31668321Scgd sb->st_mtimespec = vap->va_mtime; 31754100Smckusick sb->st_ctimespec = vap->va_ctime; 31837731Smckusick sb->st_blksize = vap->va_blocksize; 31938257Smckusick sb->st_flags = vap->va_flags; 32038257Smckusick sb->st_gen = vap->va_gen; 32138769Smckusick sb->st_blocks = vap->va_bytes / S_BLKSIZE; 32237731Smckusick return (0); 32337731Smckusick } 32437731Smckusick 32537731Smckusick /* 32650164Smckusick * File table vnode ioctl routine. 32737731Smckusick */ 32848030Smckusick vn_ioctl(fp, com, data, p) 32937731Smckusick struct file *fp; 33068171Scgd u_long com; 33137731Smckusick caddr_t data; 33248030Smckusick struct proc *p; 33337731Smckusick { 33437731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 33537731Smckusick struct vattr vattr; 33637731Smckusick int error; 33737731Smckusick 33837731Smckusick switch (vp->v_type) { 33937731Smckusick 34037731Smckusick case VREG: 34137731Smckusick case VDIR: 34237731Smckusick if (com == FIONREAD) { 34348030Smckusick if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 34437731Smckusick return (error); 34554772Storek *(int *)data = vattr.va_size - fp->f_offset; 34637731Smckusick return (0); 34718Sbill } 34837731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 34937731Smckusick return (0); /* XXX */ 35037731Smckusick /* fall into ... */ 35137731Smckusick 35237731Smckusick default: 35337731Smckusick return (ENOTTY); 35437731Smckusick 35540284Smckusick case VFIFO: 35637731Smckusick case VCHR: 35737731Smckusick case VBLK: 35848030Smckusick error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 35939564Smarc if (error == 0 && com == TIOCSCTTY) { 36067686Smckusick if (p->p_session->s_ttyvp) 36167686Smckusick vrele(p->p_session->s_ttyvp); 36247540Skarels p->p_session->s_ttyvp = vp; 36339564Smarc VREF(vp); 36439564Smarc } 36539564Smarc return (error); 36618Sbill } 36737731Smckusick } 36837731Smckusick 36937731Smckusick /* 37050164Smckusick * File table vnode select routine. 37137731Smckusick */ 37248030Smckusick vn_select(fp, which, p) 37337731Smckusick struct file *fp; 37437731Smckusick int which; 37548030Smckusick struct proc *p; 37637731Smckusick { 37747540Skarels 37840707Skarels return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 37950164Smckusick fp->f_cred, p)); 38037731Smckusick } 38137731Smckusick 38237731Smckusick /* 38369407Smckusick * Check that the vnode is still valid, and if so 38469407Smckusick * acquire requested lock. 38569407Smckusick */ 38669407Smckusick int 38769407Smckusick vn_lock(vp, flags, p) 38869407Smckusick struct vnode *vp; 38969407Smckusick int flags; 39069407Smckusick struct proc *p; 39169407Smckusick { 39269407Smckusick int error; 39369407Smckusick 39469407Smckusick do { 39569407Smckusick if ((flags & LK_INTERLOCK) == 0) 39669407Smckusick simple_lock(&vp->v_interlock); 39769407Smckusick if (vp->v_flag & VXLOCK) { 39869407Smckusick vp->v_flag |= VXWANT; 39969407Smckusick simple_unlock(&vp->v_interlock); 40069407Smckusick tsleep((caddr_t)vp, PINOD, "vn_lock", 0); 40169407Smckusick error = ENOENT; 40269407Smckusick } else { 40369407Smckusick error = VOP_LOCK(vp, flags | LK_INTERLOCK, p); 40469407Smckusick if (error == 0) 40569407Smckusick return (error); 40669407Smckusick } 40769407Smckusick flags &= ~LK_INTERLOCK; 40869407Smckusick } while (flags & LK_RETRY); 40969407Smckusick return (error); 41069407Smckusick } 41169407Smckusick 41269407Smckusick /* 41350164Smckusick * File table vnode close routine. 41437731Smckusick */ 41550164Smckusick vn_closefile(fp, p) 41650164Smckusick struct file *fp; 41748030Smckusick struct proc *p; 41837731Smckusick { 41937731Smckusick 42050164Smckusick return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 42150164Smckusick fp->f_cred, p)); 42237731Smckusick } 423