convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index 13e5172..736c330 100644 (file)
@@ -1,24 +1,30 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_vnops.c 7.39 (Berkeley) %G%
+ *     @(#)vfs_vnops.c 8.12 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "kernel.h"
-#include "file.h"
-#include "stat.h"
-#include "buf.h"
-#include "proc.h"
-#include "mount.h"
-#include "namei.h"
-#include "vnode.h"
-#include "ioctl.h"
-#include "tty.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+
 #include <vm/vm.h>
 
 struct         fileops vnops =
 #include <vm/vm.h>
 
 struct         fileops vnops =
@@ -50,7 +56,9 @@ vn_open(ndp, fmode, cmode)
                        VATTR_NULL(vap);
                        vap->va_type = VREG;
                        vap->va_mode = cmode;
                        VATTR_NULL(vap);
                        vap->va_type = VREG;
                        vap->va_mode = cmode;
-                       LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE);
+                       if (fmode & O_EXCL)
+                               vap->va_vaflags |= VA_EXCLUSIVE;
+                       VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
                        if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
                            &ndp->ni_cnd, vap))
                                return (error);
                        if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
                            &ndp->ni_cnd, vap))
                                return (error);
@@ -97,9 +105,11 @@ vn_open(ndp, fmode, cmode)
                }
        }
        if (fmode & O_TRUNC) {
                }
        }
        if (fmode & O_TRUNC) {
+               VOP_UNLOCK(vp, 0, p);                           /* XXX */
+               VOP_LEASE(vp, p, cred, LEASE_WRITE);
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);        /* XXX */
                VATTR_NULL(vap);
                vap->va_size = 0;
                VATTR_NULL(vap);
                vap->va_size = 0;
-               LEASE_CHECK(vp, p, cred, LEASE_WRITE);
                if (error = VOP_SETATTR(vp, vap, cred, p))
                        goto bad;
        }
                if (error = VOP_SETATTR(vp, vap, cred, p))
                        goto bad;
        }
@@ -181,7 +191,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
        int error;
 
        if ((ioflg & IO_NODELOCKED) == 0)
        int error;
 
        if ((ioflg & IO_NODELOCKED) == 0)
-               VOP_LOCK(vp);
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        aiov.iov_base = base;
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        aiov.iov_base = base;
@@ -192,10 +202,8 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
        auio.uio_rw = rw;
        auio.uio_procp = p;
        if (rw == UIO_READ) {
        auio.uio_rw = rw;
        auio.uio_procp = p;
        if (rw == UIO_READ) {
-               LEASE_CHECK(vp, p, cred, LEASE_READ);
                error = VOP_READ(vp, &auio, ioflg, cred);
        } else {
                error = VOP_READ(vp, &auio, ioflg, cred);
        } else {
-               LEASE_CHECK(vp, p, cred, LEASE_WRITE);
                error = VOP_WRITE(vp, &auio, ioflg, cred);
        }
        if (aresid)
                error = VOP_WRITE(vp, &auio, ioflg, cred);
        }
        if (aresid)
@@ -204,7 +212,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
                if (auio.uio_resid && error == 0)
                        error = EIO;
        if ((ioflg & IO_NODELOCKED) == 0)
                if (auio.uio_resid && error == 0)
                        error = EIO;
        if ((ioflg & IO_NODELOCKED) == 0)
-               VOP_UNLOCK(vp);
+               VOP_UNLOCK(vp, 0, p);
        return (error);
 }
 
        return (error);
 }
 
@@ -216,17 +224,18 @@ vn_read(fp, uio, cred)
        struct uio *uio;
        struct ucred *cred;
 {
        struct uio *uio;
        struct ucred *cred;
 {
-       register struct vnode *vp = (struct vnode *)fp->f_data;
+       struct vnode *vp = (struct vnode *)fp->f_data;
+       struct proc *p = uio->uio_procp;
        int count, error;
 
        int count, error;
 
-       VOP_LOCK(vp);
+       VOP_LEASE(vp, p, cred, LEASE_READ);
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        uio->uio_offset = fp->f_offset;
        count = uio->uio_resid;
        uio->uio_offset = fp->f_offset;
        count = uio->uio_resid;
-       LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ);
        error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
                cred);
        fp->f_offset += count - uio->uio_resid;
        error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
                cred);
        fp->f_offset += count - uio->uio_resid;
-       VOP_UNLOCK(vp);
+       VOP_UNLOCK(vp, 0, p);
        return (error);
 }
 
        return (error);
 }
 
@@ -238,23 +247,26 @@ vn_write(fp, uio, cred)
        struct uio *uio;
        struct ucred *cred;
 {
        struct uio *uio;
        struct ucred *cred;
 {
-       register struct vnode *vp = (struct vnode *)fp->f_data;
-       int count, error, ioflag = 0;
+       struct vnode *vp = (struct vnode *)fp->f_data;
+       struct proc *p = uio->uio_procp;
+       int count, error, ioflag = IO_UNIT;
 
        if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
                ioflag |= IO_APPEND;
        if (fp->f_flag & FNONBLOCK)
                ioflag |= IO_NDELAY;
 
        if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
                ioflag |= IO_APPEND;
        if (fp->f_flag & FNONBLOCK)
                ioflag |= IO_NDELAY;
-       VOP_LOCK(vp);
+       if ((fp->f_flag & O_FSYNC) || (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))
+               ioflag |= IO_SYNC;
+       VOP_LEASE(vp, p, cred, LEASE_WRITE);
+       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        uio->uio_offset = fp->f_offset;
        count = uio->uio_resid;
        uio->uio_offset = fp->f_offset;
        count = uio->uio_resid;
-       LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE);
        error = VOP_WRITE(vp, uio, ioflag, cred);
        if (ioflag & IO_APPEND)
                fp->f_offset = uio->uio_offset;
        else
                fp->f_offset += count - uio->uio_resid;
        error = VOP_WRITE(vp, uio, ioflag, cred);
        if (ioflag & IO_APPEND)
                fp->f_offset = uio->uio_offset;
        else
                fp->f_offset += count - uio->uio_resid;
-       VOP_UNLOCK(vp);
+       VOP_UNLOCK(vp, 0, p);
        return (error);
 }
 
        return (error);
 }
 
@@ -312,9 +324,9 @@ vn_stat(vp, sb, p)
        sb->st_gid = vap->va_gid;
        sb->st_rdev = vap->va_rdev;
        sb->st_size = vap->va_size;
        sb->st_gid = vap->va_gid;
        sb->st_rdev = vap->va_rdev;
        sb->st_size = vap->va_size;
-       sb->st_atimeval= vap->va_atime;
-       sb->st_mtimeval= vap->va_mtime;
-       sb->st_ctimeval= vap->va_ctime;
+       sb->st_atimespec = vap->va_atime;
+       sb->st_mtimespec = vap->va_mtime;
+       sb->st_ctimespec = vap->va_ctime;
        sb->st_blksize = vap->va_blocksize;
        sb->st_flags = vap->va_flags;
        sb->st_gen = vap->va_gen;
        sb->st_blksize = vap->va_blocksize;
        sb->st_flags = vap->va_flags;
        sb->st_gen = vap->va_gen;
@@ -327,7 +339,7 @@ vn_stat(vp, sb, p)
  */
 vn_ioctl(fp, com, data, p)
        struct file *fp;
  */
 vn_ioctl(fp, com, data, p)
        struct file *fp;
-       int com;
+       u_long com;
        caddr_t data;
        struct proc *p;
 {
        caddr_t data;
        struct proc *p;
 {
@@ -342,7 +354,7 @@ vn_ioctl(fp, com, data, p)
                if (com == FIONREAD) {
                        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
                                return (error);
                if (com == FIONREAD) {
                        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
                                return (error);
-                       *(off_t *)data = vattr.va_size - fp->f_offset;
+                       *(int *)data = vattr.va_size - fp->f_offset;
                        return (0);
                }
                if (com == FIONBIO || com == FIOASYNC)  /* XXX */
                        return (0);
                }
                if (com == FIONBIO || com == FIOASYNC)  /* XXX */
@@ -357,6 +369,8 @@ vn_ioctl(fp, com, data, p)
        case VBLK:
                error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
                if (error == 0 && com == TIOCSCTTY) {
        case VBLK:
                error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
                if (error == 0 && com == TIOCSCTTY) {
+                       if (p->p_session->s_ttyvp)
+                               vrele(p->p_session->s_ttyvp);
                        p->p_session->s_ttyvp = vp;
                        VREF(vp);
                }
                        p->p_session->s_ttyvp = vp;
                        VREF(vp);
                }
@@ -378,35 +392,43 @@ vn_select(fp, which, p)
 }
 
 /*
 }
 
 /*
- * File table vnode close routine.
+ * Check that the vnode is still valid, and if so
+ * acquire requested lock.
  */
  */
-vn_closefile(fp, p)
-       struct file *fp;
+int
+vn_lock(vp, flags, p)
+       struct vnode *vp;
+       int flags;
        struct proc *p;
 {
        struct proc *p;
 {
-
-       return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
-               fp->f_cred, p));
+       int error;
+       
+       do {
+               if ((flags & LK_INTERLOCK) == 0)
+                       simple_lock(&vp->v_interlock);
+               if (vp->v_flag & VXLOCK) {
+                       vp->v_flag |= VXWANT;
+                       simple_unlock(&vp->v_interlock);
+                       tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
+                       error = ENOENT;
+               } else {
+                       error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
+                       if (error == 0)
+                               return (error);
+               }
+               flags &= ~LK_INTERLOCK;
+       } while (flags & LK_RETRY);
+       return (error);
 }
 
 /*
 }
 
 /*
- * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
- *     - look up fsid in mount list (if not found ret error)
- *     - get vp by calling VFS_FHTOVP() macro
- *     - if lockflag lock it with VOP_LOCK()
+ * File table vnode close routine.
  */
  */
-vn_fhtovp(fhp, lockflag, vpp)
-       fhandle_t *fhp;
-       int lockflag;
-       struct vnode **vpp;
+vn_closefile(fp, p)
+       struct file *fp;
+       struct proc *p;
 {
 {
-       register struct mount *mp;
 
 
-       if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
-               return (ESTALE);
-       if (VFS_FHTOVP(mp, &fhp->fh_fid, 0, vpp))
-               return (ESTALE);
-       if (!lockflag)
-               VOP_UNLOCK(*vpp);
-       return (0);
+       return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
+               fp->f_cred, p));
 }
 }