123398Smckusick /* 237731Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337731Smckusick * All rights reserved. 423398Smckusick * 537731Smckusick * Redistribution and use in source and binary forms are permitted 637731Smckusick * provided that the above copyright notice and this paragraph are 737731Smckusick * duplicated in all such forms and that any documentation, 837731Smckusick * advertising materials, and other materials related to such 937731Smckusick * distribution and use acknowledge that the software was developed 1037731Smckusick * by the University of California, Berkeley. The name of the 1137731Smckusick * University may not be used to endorse or promote products derived 1237731Smckusick * from this software without specific prior written permission. 1337731Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437731Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537731Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637731Smckusick * 17*43343Smckusick * @(#)vfs_vnops.c 7.21 (Berkeley) 06/21/90 1823398Smckusick */ 1918Sbill 2017099Sbloom #include "param.h" 2117099Sbloom #include "systm.h" 2217099Sbloom #include "user.h" 2337731Smckusick #include "kernel.h" 2417099Sbloom #include "file.h" 2537731Smckusick #include "stat.h" 2637731Smckusick #include "buf.h" 2737731Smckusick #include "proc.h" 2837731Smckusick #include "uio.h" 2917099Sbloom #include "socket.h" 3017099Sbloom #include "socketvar.h" 3137731Smckusick #include "mount.h" 3237731Smckusick #include "vnode.h" 3337731Smckusick #include "ioctl.h" 3437731Smckusick #include "tty.h" 3518Sbill 3637731Smckusick int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 3737731Smckusick struct fileops vnops = 3837731Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 3937520Smckusick 4018Sbill /* 4137731Smckusick * Common code for vnode open operations. 4237731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 4318Sbill */ 4437731Smckusick vn_open(ndp, fmode, cmode) 4537731Smckusick register struct nameidata *ndp; 4637731Smckusick int fmode, cmode; 4737731Smckusick { 4837731Smckusick register struct vnode *vp; 4937731Smckusick struct vattr vat; 5037731Smckusick struct vattr *vap = &vat; 5137731Smckusick int error; 5237731Smckusick 5337731Smckusick if (fmode & FCREAT) { 5437731Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 5537731Smckusick if ((fmode & FEXCL) == 0) 5637731Smckusick ndp->ni_nameiop |= FOLLOW; 5737731Smckusick if (error = namei(ndp)) 5837731Smckusick return (error); 5937731Smckusick if (ndp->ni_vp == NULL) { 6041362Smckusick VATTR_NULL(vap); 6137731Smckusick vap->va_type = VREG; 6237731Smckusick vap->va_mode = cmode; 6337731Smckusick if (error = VOP_CREATE(ndp, vap)) 6437731Smckusick return (error); 6537731Smckusick fmode &= ~FTRUNC; 6637731Smckusick vp = ndp->ni_vp; 6737731Smckusick } else { 6839761Smckusick if (ndp->ni_dvp == ndp->ni_vp) 6939761Smckusick vrele(ndp->ni_dvp); 70*43343Smckusick else 7139761Smckusick vput(ndp->ni_dvp); 7239761Smckusick ndp->ni_dvp = NULL; 7337731Smckusick vp = ndp->ni_vp; 7437731Smckusick if (fmode & FEXCL) { 7537731Smckusick error = EEXIST; 7637731Smckusick goto bad; 7737731Smckusick } 7837731Smckusick fmode &= ~FCREAT; 7937731Smckusick } 8037731Smckusick } else { 8137731Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 8237731Smckusick if (error = namei(ndp)) 8337731Smckusick return (error); 8437731Smckusick vp = ndp->ni_vp; 8537731Smckusick } 8637731Smckusick if (vp->v_type == VSOCK) { 8737731Smckusick error = EOPNOTSUPP; 8837731Smckusick goto bad; 8937731Smckusick } 9037731Smckusick if ((fmode & FCREAT) == 0) { 9137731Smckusick if (fmode & FREAD) { 9238401Smckusick if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred)) 9337731Smckusick goto bad; 9437731Smckusick } 9537731Smckusick if (fmode & (FWRITE|FTRUNC)) { 9637731Smckusick if (vp->v_type == VDIR) { 9737731Smckusick error = EISDIR; 9837731Smckusick goto bad; 9937731Smckusick } 10038401Smckusick if ((error = vn_writechk(vp)) || 10138401Smckusick (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) 10238401Smckusick goto bad; 10337731Smckusick } 10437731Smckusick } 10537731Smckusick if (fmode & FTRUNC) { 10641362Smckusick VATTR_NULL(vap); 10737731Smckusick vap->va_size = 0; 10837731Smckusick if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 10937731Smckusick goto bad; 11037731Smckusick } 11137731Smckusick VOP_UNLOCK(vp); 11238351Smckusick error = VOP_OPEN(vp, fmode, ndp->ni_cred); 11338351Smckusick if (error) 11438351Smckusick vrele(vp); 11538351Smckusick return (error); 11637731Smckusick 11737731Smckusick bad: 11837731Smckusick vput(vp); 11940707Skarels return (error); 12037731Smckusick } 12137731Smckusick 12237731Smckusick /* 12338401Smckusick * Check for write permissions on the specified vnode. 12438401Smckusick * The read-only status of the file system is checked. 12538401Smckusick * Also, prototype text segments cannot be written. 12637731Smckusick */ 12738401Smckusick vn_writechk(vp) 12837731Smckusick register struct vnode *vp; 12918Sbill { 13018Sbill 13138401Smckusick /* 13238401Smckusick * Disallow write attempts on read-only file systems; 13338401Smckusick * unless the file is a socket or a block or character 13438401Smckusick * device resident on the file system. 13538401Smckusick */ 13641400Smckusick if ((vp->v_mount->mnt_flag & MNT_RDONLY) && vp->v_type != VCHR && 13738401Smckusick vp->v_type != VBLK && vp->v_type != VSOCK) 13838401Smckusick return (EROFS); 13938401Smckusick /* 14038401Smckusick * If there's shared text associated with 14138401Smckusick * the vnode, try to free it up once. If 14238401Smckusick * we fail, we can't allow writing. 14338401Smckusick */ 14438401Smckusick if (vp->v_flag & VTEXT) 14538401Smckusick xrele(vp); 14638401Smckusick if (vp->v_flag & VTEXT) 14738401Smckusick return (ETXTBSY); 14838401Smckusick return (0); 14937731Smckusick } 15037731Smckusick 15137731Smckusick /* 15237731Smckusick * Vnode version of rdwri() for calls on file systems. 15337731Smckusick */ 15437731Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 15537731Smckusick enum uio_rw rw; 15637731Smckusick struct vnode *vp; 15737731Smckusick caddr_t base; 15837731Smckusick int len; 15937731Smckusick off_t offset; 16037731Smckusick enum uio_seg segflg; 16137731Smckusick int ioflg; 16237731Smckusick struct ucred *cred; 16337731Smckusick int *aresid; 16437731Smckusick { 16537731Smckusick struct uio auio; 16637731Smckusick struct iovec aiov; 16737731Smckusick int error; 16837731Smckusick 16939590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 17039590Smckusick VOP_LOCK(vp); 17137731Smckusick auio.uio_iov = &aiov; 17237731Smckusick auio.uio_iovcnt = 1; 17337731Smckusick aiov.iov_base = base; 17437731Smckusick aiov.iov_len = len; 17537731Smckusick auio.uio_resid = len; 17637731Smckusick auio.uio_offset = offset; 17737731Smckusick auio.uio_segflg = segflg; 17837731Smckusick auio.uio_rw = rw; 17937731Smckusick if (rw == UIO_READ) 18039590Smckusick error = VOP_READ(vp, &auio, ioflg, cred); 18137731Smckusick else 18239590Smckusick error = VOP_WRITE(vp, &auio, ioflg, cred); 18337731Smckusick if (aresid) 18437731Smckusick *aresid = auio.uio_resid; 18537731Smckusick else 18637731Smckusick if (auio.uio_resid && error == 0) 18737731Smckusick error = EIO; 18839590Smckusick if ((ioflg & IO_NODELOCKED) == 0) 18939590Smckusick VOP_UNLOCK(vp); 19037731Smckusick return (error); 19137731Smckusick } 19237731Smckusick 19337731Smckusick vn_read(fp, uio, cred) 19437731Smckusick struct file *fp; 19537731Smckusick struct uio *uio; 19637731Smckusick struct ucred *cred; 19737731Smckusick { 19839590Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 19939590Smckusick int count, error; 20037731Smckusick 20139590Smckusick VOP_LOCK(vp); 20239590Smckusick uio->uio_offset = fp->f_offset; 20339590Smckusick count = uio->uio_resid; 20439590Smckusick error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); 20539590Smckusick fp->f_offset += count - uio->uio_resid; 20639590Smckusick VOP_UNLOCK(vp); 20739590Smckusick return (error); 20837731Smckusick } 20937731Smckusick 21037731Smckusick vn_write(fp, uio, cred) 21137731Smckusick struct file *fp; 21237731Smckusick struct uio *uio; 21337731Smckusick struct ucred *cred; 21437731Smckusick { 21537731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 21639590Smckusick int count, error, ioflag = 0; 21737731Smckusick 21837731Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 21937731Smckusick ioflag |= IO_APPEND; 22037731Smckusick if (fp->f_flag & FNDELAY) 22137731Smckusick ioflag |= IO_NDELAY; 22239590Smckusick VOP_LOCK(vp); 22339590Smckusick uio->uio_offset = fp->f_offset; 22439590Smckusick count = uio->uio_resid; 22539590Smckusick error = VOP_WRITE(vp, uio, ioflag, cred); 22639590Smckusick if (ioflag & IO_APPEND) 22739590Smckusick fp->f_offset = uio->uio_offset; 22839590Smckusick else 22939590Smckusick fp->f_offset += count - uio->uio_resid; 23039590Smckusick VOP_UNLOCK(vp); 23139590Smckusick return (error); 23237731Smckusick } 23337731Smckusick 23437731Smckusick /* 23537731Smckusick * Get stat info for a vnode. 23637731Smckusick */ 23737731Smckusick vn_stat(vp, sb) 23837731Smckusick struct vnode *vp; 23937731Smckusick register struct stat *sb; 24037731Smckusick { 24137731Smckusick struct vattr vattr; 24237731Smckusick register struct vattr *vap; 24337731Smckusick int error; 24437731Smckusick u_short mode; 24537731Smckusick 24637731Smckusick vap = &vattr; 24737731Smckusick error = VOP_GETATTR(vp, vap, u.u_cred); 24837731Smckusick if (error) 24937731Smckusick return (error); 25037731Smckusick /* 25137731Smckusick * Copy from vattr table 25237731Smckusick */ 25337731Smckusick sb->st_dev = vap->va_fsid; 25437731Smckusick sb->st_ino = vap->va_fileid; 25537731Smckusick mode = vap->va_mode; 25637731Smckusick switch (vp->v_type) { 25737731Smckusick case VREG: 25839382Smckusick mode |= S_IFREG; 25937731Smckusick break; 26037731Smckusick case VDIR: 26139382Smckusick mode |= S_IFDIR; 26237731Smckusick break; 26337731Smckusick case VBLK: 26439382Smckusick mode |= S_IFBLK; 26537731Smckusick break; 26637731Smckusick case VCHR: 26739382Smckusick mode |= S_IFCHR; 26837731Smckusick break; 26937731Smckusick case VLNK: 27039382Smckusick mode |= S_IFLNK; 27137731Smckusick break; 27237731Smckusick case VSOCK: 27339382Smckusick mode |= S_IFSOCK; 27437731Smckusick break; 27540284Smckusick case VFIFO: 27640284Smckusick mode |= S_IFIFO; 27740284Smckusick break; 27837731Smckusick default: 27937731Smckusick return (EBADF); 28037731Smckusick }; 28137731Smckusick sb->st_mode = mode; 28237731Smckusick sb->st_nlink = vap->va_nlink; 28337731Smckusick sb->st_uid = vap->va_uid; 28437731Smckusick sb->st_gid = vap->va_gid; 28537731Smckusick sb->st_rdev = vap->va_rdev; 28637731Smckusick sb->st_size = vap->va_size; 28737731Smckusick sb->st_atime = vap->va_atime.tv_sec; 28837731Smckusick sb->st_spare1 = 0; 28937731Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 29037731Smckusick sb->st_spare2 = 0; 29137731Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 29237731Smckusick sb->st_spare3 = 0; 29337731Smckusick sb->st_blksize = vap->va_blocksize; 29438257Smckusick sb->st_flags = vap->va_flags; 29538257Smckusick sb->st_gen = vap->va_gen; 29638769Smckusick sb->st_blocks = vap->va_bytes / S_BLKSIZE; 29737731Smckusick return (0); 29837731Smckusick } 29937731Smckusick 30037731Smckusick /* 30137731Smckusick * Vnode ioctl call 30237731Smckusick */ 30337731Smckusick vn_ioctl(fp, com, data) 30437731Smckusick struct file *fp; 30537731Smckusick int com; 30637731Smckusick caddr_t data; 30737731Smckusick { 30837731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 30937731Smckusick struct vattr vattr; 31037731Smckusick int error; 31137731Smckusick 31237731Smckusick switch (vp->v_type) { 31337731Smckusick 31437731Smckusick case VREG: 31537731Smckusick case VDIR: 31637731Smckusick if (com == FIONREAD) { 31737731Smckusick if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 31837731Smckusick return (error); 31937731Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 32037731Smckusick return (0); 32118Sbill } 32237731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 32337731Smckusick return (0); /* XXX */ 32437731Smckusick /* fall into ... */ 32537731Smckusick 32637731Smckusick default: 32737731Smckusick return (ENOTTY); 32837731Smckusick 32940284Smckusick case VFIFO: 33037731Smckusick case VCHR: 33137731Smckusick case VBLK: 33237731Smckusick u.u_r.r_val1 = 0; 33339564Smarc error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred); 33439564Smarc if (error == 0 && com == TIOCSCTTY) { 33539564Smarc u.u_procp->p_session->s_ttyvp = vp; 33639564Smarc VREF(vp); 33739564Smarc } 33839564Smarc return (error); 33918Sbill } 34037731Smckusick } 34137731Smckusick 34237731Smckusick /* 34337731Smckusick * Vnode select call 34437731Smckusick */ 34537731Smckusick vn_select(fp, which) 34637731Smckusick struct file *fp; 34737731Smckusick int which; 34837731Smckusick { 34940707Skarels return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 35040284Smckusick u.u_cred)); 35137731Smckusick } 35237731Smckusick 35337731Smckusick /* 35437731Smckusick * Vnode close call 35537731Smckusick */ 35637731Smckusick vn_close(fp) 35737731Smckusick register struct file *fp; 35837731Smckusick { 35937731Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 36037731Smckusick int error; 36137731Smckusick 36237731Smckusick if (fp->f_flag & (FSHLOCK|FEXLOCK)) 36337731Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 36411162Ssam /* 36537731Smckusick * Must delete vnode reference from this file entry 36637731Smckusick * before VOP_CLOSE, so that only other references 36737731Smckusick * will prevent close. 36811162Ssam */ 36937731Smckusick fp->f_data = (caddr_t) 0; 37037731Smckusick error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 37137731Smckusick vrele(vp); 37237731Smckusick return (error); 37337731Smckusick } 37437731Smckusick 37537731Smckusick /* 37637731Smckusick * Place an advisory lock on a vnode. 37737731Smckusick * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 37837731Smckusick */ 37937731Smckusick vn_lock(fp, cmd) 38037731Smckusick register struct file *fp; 38137731Smckusick int cmd; 38237731Smckusick { 38337731Smckusick register int priority = PLOCK; 38437731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 38540707Skarels int error = 0; 38640707Skarels static char lockstr[] = "flock"; 38737731Smckusick 38837731Smckusick if ((cmd & LOCK_EX) == 0) 38937731Smckusick priority += 4; 39040707Skarels priority |= PCATCH; 39140707Skarels 39211162Ssam /* 39337731Smckusick * If there's a exclusive lock currently applied 39437731Smckusick * to the file, then we've gotta wait for the 39537731Smckusick * lock with everyone else. 39611162Ssam */ 39737731Smckusick again: 39837731Smckusick while (vp->v_flag & VEXLOCK) { 39937731Smckusick /* 40037731Smckusick * If we're holding an exclusive 40137731Smckusick * lock, then release it. 40237731Smckusick */ 40337731Smckusick if (fp->f_flag & FEXLOCK) { 40437731Smckusick vn_unlock(fp, FEXLOCK); 40537731Smckusick continue; 40637731Smckusick } 40737731Smckusick if (cmd & LOCK_NB) 40837731Smckusick return (EWOULDBLOCK); 40937731Smckusick vp->v_flag |= VLWAIT; 41040707Skarels if (error = tsleep((caddr_t)&vp->v_exlockc, priority, 41140707Skarels lockstr, 0)) 41240707Skarels return (error); 41318Sbill } 41440707Skarels if (error = 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 41537731Smckusick /* 41637731Smckusick * Must wait for any shared locks to finish 41737731Smckusick * before we try to apply a exclusive lock. 41837731Smckusick * 41937731Smckusick * If we're holding a shared 42037731Smckusick * lock, then release it. 42137731Smckusick */ 42237731Smckusick if (fp->f_flag & FSHLOCK) { 42337731Smckusick vn_unlock(fp, FSHLOCK); 42437731Smckusick goto again; 42537731Smckusick } 42637731Smckusick if (cmd & LOCK_NB) 42737731Smckusick return (EWOULDBLOCK); 42837731Smckusick vp->v_flag |= VLWAIT; 42940707Skarels if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH, 43040707Skarels lockstr, 0) == 0) 43140707Skarels return (error); 43237731Smckusick } 43337731Smckusick if (fp->f_flag & FEXLOCK) 43437731Smckusick panic("vn_lock"); 43537731Smckusick if (cmd & LOCK_EX) { 43637731Smckusick cmd &= ~LOCK_SH; 43737731Smckusick vp->v_exlockc++; 43837731Smckusick vp->v_flag |= VEXLOCK; 43937731Smckusick fp->f_flag |= FEXLOCK; 44037731Smckusick } 44137731Smckusick if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 44237731Smckusick vp->v_shlockc++; 44337731Smckusick vp->v_flag |= VSHLOCK; 44437731Smckusick fp->f_flag |= FSHLOCK; 44537731Smckusick } 44637731Smckusick return (0); 44718Sbill } 44818Sbill 44918Sbill /* 45037731Smckusick * Unlock a file. 45118Sbill */ 45237731Smckusick vn_unlock(fp, kind) 45337731Smckusick register struct file *fp; 45437731Smckusick int kind; 45518Sbill { 45637731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 45737731Smckusick int flags; 45818Sbill 45937731Smckusick kind &= fp->f_flag; 46037731Smckusick if (vp == NULL || kind == 0) 46137731Smckusick return; 46237731Smckusick flags = vp->v_flag; 46337731Smckusick if (kind & FSHLOCK) { 46437731Smckusick if ((flags & VSHLOCK) == 0) 46537731Smckusick panic("vn_unlock: SHLOCK"); 46637731Smckusick if (--vp->v_shlockc == 0) { 46737731Smckusick vp->v_flag &= ~VSHLOCK; 46837731Smckusick if (flags & VLWAIT) 46937731Smckusick wakeup((caddr_t)&vp->v_shlockc); 47037731Smckusick } 47137731Smckusick fp->f_flag &= ~FSHLOCK; 47237552Smckusick } 47337731Smckusick if (kind & FEXLOCK) { 47437731Smckusick if ((flags & VEXLOCK) == 0) 47537731Smckusick panic("vn_unlock: EXLOCK"); 47637731Smckusick if (--vp->v_exlockc == 0) { 47737731Smckusick vp->v_flag &= ~(VEXLOCK|VLWAIT); 47837731Smckusick if (flags & VLWAIT) 47937731Smckusick wakeup((caddr_t)&vp->v_exlockc); 48037731Smckusick } 48137731Smckusick fp->f_flag &= ~FEXLOCK; 48237731Smckusick } 48318Sbill } 48418Sbill 48518Sbill /* 48637731Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 48737731Smckusick * - look up fsid in mount list (if not found ret error) 48837731Smckusick * - get vp by calling VFS_FHTOVP() macro 48937731Smckusick * - if lockflag lock it with VOP_LOCK() 49018Sbill */ 49137731Smckusick vn_fhtovp(fhp, lockflag, vpp) 49237731Smckusick fhandle_t *fhp; 49337731Smckusick int lockflag; 49437731Smckusick struct vnode **vpp; 49518Sbill { 49637731Smckusick register struct mount *mp; 49718Sbill 49837731Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 49937731Smckusick return (ESTALE); 50038146Smckusick if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 50138146Smckusick return (ESTALE); 50238146Smckusick if (!lockflag) 50338146Smckusick VOP_UNLOCK(*vpp); 50437731Smckusick return (0); 50537731Smckusick } 50637731Smckusick 50737731Smckusick /* 50837731Smckusick * Noop 50937731Smckusick */ 51037731Smckusick vfs_noop() 51137731Smckusick { 51237731Smckusick 51337731Smckusick return (ENXIO); 51437731Smckusick } 51537731Smckusick 51637731Smckusick /* 51737731Smckusick * Null op 51837731Smckusick */ 51937731Smckusick vfs_nullop() 52037731Smckusick { 52137731Smckusick 52237731Smckusick return (0); 52337731Smckusick } 524