convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / vfs_vnops.c
index 77f94e0..736c330 100644 (file)
@@ -9,7 +9,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_vnops.c 8.6 (Berkeley) %G%
+ *     @(#)vfs_vnops.c 8.12 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -56,6 +56,8 @@ 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;
+                       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))
                        VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
                        if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
                            &ndp->ni_cnd, vap))
@@ -103,9 +105,9 @@ vn_open(ndp, fmode, cmode)
                }
        }
        if (fmode & O_TRUNC) {
                }
        }
        if (fmode & O_TRUNC) {
-               VOP_UNLOCK(vp);                         /* XXX */
+               VOP_UNLOCK(vp, 0, p);                           /* XXX */
                VOP_LEASE(vp, p, cred, LEASE_WRITE);
                VOP_LEASE(vp, p, cred, LEASE_WRITE);
-               VOP_LOCK(vp);                                   /* XXX */
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);        /* XXX */
                VATTR_NULL(vap);
                vap->va_size = 0;
                if (error = VOP_SETATTR(vp, vap, cred, p))
                VATTR_NULL(vap);
                vap->va_size = 0;
                if (error = VOP_SETATTR(vp, vap, cred, p))
@@ -189,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;
@@ -210,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);
 }
 
@@ -222,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_LEASE(vp, uio->uio_procp, cred, LEASE_READ);
-       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;
        error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
                cred);
        fp->f_offset += count - uio->uio_resid;
        uio->uio_offset = 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);
 }
 
@@ -244,15 +247,18 @@ 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;
+       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;
        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;
-       VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE);
-       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;
        error = VOP_WRITE(vp, uio, ioflag, cred);
        uio->uio_offset = fp->f_offset;
        count = uio->uio_resid;
        error = VOP_WRITE(vp, uio, ioflag, cred);
@@ -260,7 +266,7 @@ vn_write(fp, uio, cred)
                fp->f_offset = uio->uio_offset;
        else
                fp->f_offset += count - uio->uio_resid;
                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);
 }
 
@@ -319,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;
@@ -385,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.
  */