X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1c15e88899094343f75aeba04122cd96a96b428e..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/sys/kern/vfs_vnops.c diff --git a/usr/src/sys/kern/vfs_vnops.c b/usr/src/sys/kern/vfs_vnops.c index ecfd253703..5c9f4af7a2 100644 --- a/usr/src/sys/kern/vfs_vnops.c +++ b/usr/src/sys/kern/vfs_vnops.c @@ -2,87 +2,99 @@ * Copyright (c) 1982, 1986, 1989 Regents of the University of California. * All rights reserved. * - * Redistribution is only permitted until one year after the first shipment - * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and - * binary forms are permitted provided that: (1) source distributions retain - * this entire copyright notice and comment, and (2) distributions including - * binaries display the following acknowledgement: This product includes - * software developed by the University of California, Berkeley and its - * contributors'' in the documentation or other materials provided with the - * distribution and in all advertising materials mentioning features or use - * of this software. Neither the name of the University nor the names of - * its contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * @(#)vfs_vnops.c 7.23 (Berkeley) 6/28/90 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vfs_vnops.c 7.33 (Berkeley) 6/27/91 */ #include "param.h" #include "systm.h" -#include "user.h" #include "kernel.h" #include "file.h" #include "stat.h" #include "buf.h" #include "proc.h" -#include "uio.h" -#include "socket.h" -#include "socketvar.h" #include "mount.h" +#include "namei.h" #include "vnode.h" #include "ioctl.h" #include "tty.h" -int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); struct fileops vnops = - { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; + { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; /* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. */ -vn_open(ndp, fmode, cmode) +vn_open(ndp, p, fmode, cmode) register struct nameidata *ndp; + struct proc *p; int fmode, cmode; { register struct vnode *vp; + register struct ucred *cred = p->p_ucred; struct vattr vat; struct vattr *vap = &vat; int error; - if (fmode & FCREAT) { + if (fmode & O_CREAT) { ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; - if ((fmode & FEXCL) == 0) + if ((fmode & O_EXCL) == 0) ndp->ni_nameiop |= FOLLOW; - if (error = namei(ndp)) + if (error = namei(ndp, p)) return (error); if (ndp->ni_vp == NULL) { VATTR_NULL(vap); vap->va_type = VREG; vap->va_mode = cmode; - if (error = VOP_CREATE(ndp, vap)) + if (error = VOP_CREATE(ndp, vap, p)) return (error); - fmode &= ~FTRUNC; + fmode &= ~O_TRUNC; vp = ndp->ni_vp; } else { + VOP_ABORTOP(ndp); if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else vput(ndp->ni_dvp); ndp->ni_dvp = NULL; vp = ndp->ni_vp; - if (fmode & FEXCL) { + if (fmode & O_EXCL) { error = EEXIST; goto bad; } - fmode &= ~FCREAT; + fmode &= ~O_CREAT; } } else { ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; - if (error = namei(ndp)) + if (error = namei(ndp, p)) return (error); vp = ndp->ni_vp; } @@ -90,33 +102,32 @@ vn_open(ndp, fmode, cmode) error = EOPNOTSUPP; goto bad; } - if ((fmode & FCREAT) == 0) { + if ((fmode & O_CREAT) == 0) { if (fmode & FREAD) { - if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred)) + if (error = VOP_ACCESS(vp, VREAD, cred, p)) goto bad; } - if (fmode & (FWRITE|FTRUNC)) { + if (fmode & (FWRITE | O_TRUNC)) { if (vp->v_type == VDIR) { error = EISDIR; goto bad; } if ((error = vn_writechk(vp)) || - (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) + (error = VOP_ACCESS(vp, VWRITE, cred, p))) goto bad; } } - if (fmode & FTRUNC) { + if (fmode & O_TRUNC) { VATTR_NULL(vap); vap->va_size = 0; - if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) + if (error = VOP_SETATTR(vp, vap, cred, p)) goto bad; } - VOP_UNLOCK(vp); - error = VOP_OPEN(vp, fmode, ndp->ni_cred); - if (error) - vrele(vp); - return (error); - + if (error = VOP_OPEN(vp, fmode, cred, p)) + goto bad; + if (fmode & FWRITE) + vp->v_writecount++; + return (0); bad: vput(vp); return (error); @@ -136,25 +147,44 @@ vn_writechk(vp) * unless the file is a socket or a block or character * device resident on the file system. */ - if ((vp->v_mount->mnt_flag & MNT_RDONLY) && vp->v_type != VCHR && - vp->v_type != VBLK && vp->v_type != VSOCK) - return (EROFS); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: + return (EROFS); + } + } /* * If there's shared text associated with * the vnode, try to free it up once. If * we fail, we can't allow writing. */ - if (vp->v_flag & VTEXT) - xrele(vp); - if (vp->v_flag & VTEXT) + if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) return (ETXTBSY); return (0); } /* - * Vnode version of rdwri() for calls on file systems. + * Vnode close call */ -vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) +vn_close(vp, flags, cred, p) + register struct vnode *vp; + int flags; + struct ucred *cred; + struct proc *p; +{ + int error; + + if (flags & FWRITE) + vp->v_writecount--; + error = VOP_CLOSE(vp, flags, cred, p); + vrele(vp); + return (error); +} + +/* + * Package up an I/O request on a vnode into a uio and do it. + */ +vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) enum uio_rw rw; struct vnode *vp; caddr_t base; @@ -164,6 +194,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) int ioflg; struct ucred *cred; int *aresid; + struct proc *p; { struct uio auio; struct iovec aiov; @@ -179,6 +210,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) auio.uio_offset = offset; auio.uio_segflg = segflg; auio.uio_rw = rw; + auio.uio_procp = p; if (rw == UIO_READ) error = VOP_READ(vp, &auio, ioflg, cred); else @@ -193,6 +225,9 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) return (error); } +/* + * File table vnode read routine. + */ vn_read(fp, uio, cred) struct file *fp; struct uio *uio; @@ -204,12 +239,16 @@ vn_read(fp, uio, cred) VOP_LOCK(vp); uio->uio_offset = fp->f_offset; count = uio->uio_resid; - error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); + error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, + cred); fp->f_offset += count - uio->uio_resid; VOP_UNLOCK(vp); return (error); } +/* + * File table vnode write routine. + */ vn_write(fp, uio, cred) struct file *fp; struct uio *uio; @@ -218,9 +257,9 @@ vn_write(fp, uio, cred) register struct vnode *vp = (struct vnode *)fp->f_data; int count, error, ioflag = 0; - if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) + if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) ioflag |= IO_APPEND; - if (fp->f_flag & FNDELAY) + if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; VOP_LOCK(vp); uio->uio_offset = fp->f_offset; @@ -235,11 +274,12 @@ vn_write(fp, uio, cred) } /* - * Get stat info for a vnode. + * File table vnode stat routine. */ -vn_stat(vp, sb) +vn_stat(vp, sb, p) struct vnode *vp; register struct stat *sb; + struct proc *p; { struct vattr vattr; register struct vattr *vap; @@ -247,7 +287,7 @@ vn_stat(vp, sb) u_short mode; vap = &vattr; - error = VOP_GETATTR(vp, vap, u.u_cred); + error = VOP_GETATTR(vp, vap, p->p_ucred, p); if (error) return (error); /* @@ -301,12 +341,13 @@ vn_stat(vp, sb) } /* - * Vnode ioctl call + * File table vnode ioctl routine. */ -vn_ioctl(fp, com, data) +vn_ioctl(fp, com, data, p) struct file *fp; int com; caddr_t data; + struct proc *p; { register struct vnode *vp = ((struct vnode *)fp->f_data); struct vattr vattr; @@ -317,7 +358,7 @@ vn_ioctl(fp, com, data) case VREG: case VDIR: if (com == FIONREAD) { - if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) + if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) return (error); *(off_t *)data = vattr.va_size - fp->f_offset; return (0); @@ -332,9 +373,9 @@ vn_ioctl(fp, com, data) case VFIFO: case VCHR: case VBLK: - error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred); + error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); if (error == 0 && com == TIOCSCTTY) { - u.u_procp->p_session->s_ttyvp = vp; + p->p_session->s_ttyvp = vp; VREF(vp); } return (error); @@ -342,146 +383,28 @@ vn_ioctl(fp, com, data) } /* - * Vnode select call + * File table vnode select routine. */ -vn_select(fp, which) +vn_select(fp, which, p) struct file *fp; int which; + struct proc *p; { - return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, - u.u_cred)); -} - -/* - * Vnode close call - */ -vn_close(fp) - register struct file *fp; -{ - struct vnode *vp = ((struct vnode *)fp->f_data); - int error; - - if (fp->f_flag & (FSHLOCK|FEXLOCK)) - vn_unlock(fp, FSHLOCK|FEXLOCK); - /* - * Must delete vnode reference from this file entry - * before VOP_CLOSE, so that only other references - * will prevent close. - */ - fp->f_data = (caddr_t) 0; - error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); - vrele(vp); - return (error); -} - -/* - * Place an advisory lock on a vnode. - * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries - */ -vn_lock(fp, cmd) - register struct file *fp; - int cmd; -{ - register int priority = PLOCK; - register struct vnode *vp = (struct vnode *)fp->f_data; - int error = 0; - static char lockstr[] = "flock"; - - if ((cmd & LOCK_EX) == 0) - priority += 4; - priority |= PCATCH; - /* - * If there's a exclusive lock currently applied - * to the file, then we've gotta wait for the - * lock with everyone else. - */ -again: - while (vp->v_flag & VEXLOCK) { - /* - * If we're holding an exclusive - * lock, then release it. - */ - if (fp->f_flag & FEXLOCK) { - vn_unlock(fp, FEXLOCK); - continue; - } - if (cmd & LOCK_NB) - return (EWOULDBLOCK); - vp->v_flag |= VLWAIT; - if (error = tsleep((caddr_t)&vp->v_exlockc, priority, - lockstr, 0)) - return (error); - } - if (error = 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { - /* - * Must wait for any shared locks to finish - * before we try to apply a exclusive lock. - * - * If we're holding a shared - * lock, then release it. - */ - if (fp->f_flag & FSHLOCK) { - vn_unlock(fp, FSHLOCK); - goto again; - } - if (cmd & LOCK_NB) - return (EWOULDBLOCK); - vp->v_flag |= VLWAIT; - if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH, - lockstr, 0) == 0) - return (error); - } - if (fp->f_flag & FEXLOCK) - panic("vn_lock"); - if (cmd & LOCK_EX) { - cmd &= ~LOCK_SH; - vp->v_exlockc++; - vp->v_flag |= VEXLOCK; - fp->f_flag |= FEXLOCK; - } - if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { - vp->v_shlockc++; - vp->v_flag |= VSHLOCK; - fp->f_flag |= FSHLOCK; - } - return (0); + return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, + fp->f_cred, p)); } /* - * Unlock a file. + * File table vnode close routine. */ -vn_unlock(fp, kind) - register struct file *fp; - int kind; +vn_closefile(fp, p) + struct file *fp; + struct proc *p; { - register struct vnode *vp = (struct vnode *)fp->f_data; - int flags; - kind &= fp->f_flag; - if (vp == NULL || kind == 0) - return; - flags = vp->v_flag; - if (kind & FSHLOCK) { - if ((flags & VSHLOCK) == 0) - panic("vn_unlock: SHLOCK"); - if (--vp->v_shlockc == 0) { - vp->v_flag &= ~VSHLOCK; - if (flags & VLWAIT) - wakeup((caddr_t)&vp->v_shlockc); - } - fp->f_flag &= ~FSHLOCK; - } - if (kind & FEXLOCK) { - if ((flags & VEXLOCK) == 0) - panic("vn_unlock: EXLOCK"); - if (--vp->v_exlockc == 0) { - vp->v_flag &= ~(VEXLOCK|VLWAIT); - if (flags & VLWAIT) - wakeup((caddr_t)&vp->v_exlockc); - } - fp->f_flag &= ~FEXLOCK; - } + return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, + fp->f_cred, p)); } /* @@ -505,21 +428,3 @@ vn_fhtovp(fhp, lockflag, vpp) VOP_UNLOCK(*vpp); return (0); } - -/* - * Noop - */ -vfs_noop() -{ - - return (ENXIO); -} - -/* - * Null op - */ -vfs_nullop() -{ - - return (0); -}