convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index e66b2ea..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.45 (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);
 }
 
@@ -313,7 +325,7 @@ vn_stat(vp, sb, p)
        sb->st_rdev = vap->va_rdev;
        sb->st_size = vap->va_size;
        sb->st_atimespec = vap->va_atime;
        sb->st_rdev = vap->va_rdev;
        sb->st_size = vap->va_size;
        sb->st_atimespec = vap->va_atime;
-       sb->st_mtimespec= vap->va_mtime;
+       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_ctimespec = vap->va_ctime;
        sb->st_blksize = vap->va_blocksize;
        sb->st_flags = vap->va_flags;
@@ -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;
 {
@@ -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);
                }
@@ -377,6 +391,36 @@ vn_select(fp, which, p)
                fp->f_cred, p));
 }
 
                fp->f_cred, p));
 }
 
+/*
+ * Check that the vnode is still valid, and if so
+ * acquire requested lock.
+ */
+int
+vn_lock(vp, flags, p)
+       struct vnode *vp;
+       int flags;
+       struct proc *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);
+}
+
 /*
  * File table vnode close routine.
  */
 /*
  * File table vnode close routine.
  */