summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_vnops.c')
-rw-r--r--sys/kern/vfs_vnops.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index b99a001a165..3037cad20fe 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.5 1997/08/04 08:24:54 deraadt Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.6 1997/10/06 15:12:45 csapuntz Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -133,9 +133,9 @@ vn_open(ndp, fmode, cmode)
}
}
if (fmode & O_TRUNC) {
- VOP_UNLOCK(vp); /* XXX */
+ VOP_UNLOCK(vp, 0, p); /* XXX */
VOP_LEASE(vp, p, cred, LEASE_WRITE);
- VOP_LOCK(vp); /* XXX */
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
VATTR_NULL(&va);
va.va_size = 0;
if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
@@ -153,14 +153,14 @@ bad:
/*
* Check for write permissions on the specified vnode.
- * The read-only status of the file system is checked.
- * Also, prototype text segments cannot be written.
+ * Prototype text segments cannot be written.
*/
int
vn_writechk(vp)
register struct vnode *vp;
{
+#if 0
/*
* Disallow write attempts on read-only file systems;
* unless the file is a socket or a block or character
@@ -175,6 +175,7 @@ vn_writechk(vp)
break;
}
}
+#endif
/*
* If there's shared text associated with
* the vnode, try to free it up once. If
@@ -225,7 +226,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
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;
@@ -246,7 +247,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)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -261,16 +262,17 @@ vn_read(fp, uio, cred)
{
register struct vnode *vp = (struct vnode *)fp->f_data;
int count, error = 0;
+ struct proc *p = uio->uio_procp;
VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
uio->uio_offset = fp->f_offset;
count = uio->uio_resid;
if (vp->v_type != VDIR)
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);
}
@@ -284,14 +286,18 @@ vn_write(fp, uio, cred)
struct ucred *cred;
{
register 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 ((fp->f_flag & O_FSYNC) ||
+ (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
+ ioflag |= IO_SYNC;
VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE);
- VOP_LOCK(vp);
+ 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);
@@ -299,7 +305,7 @@ vn_write(fp, uio, cred)
fp->f_offset = uio->uio_offset;
else
fp->f_offset += count - uio->uio_resid;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -427,6 +433,36 @@ vn_select(fp, which, 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.
*/
int