summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-07-21 08:30:35 +0000
committeranton <anton@cvs.openbsd.org>2019-07-21 08:30:35 +0000
commitefc8fe3631b3dcc5853f0c28164f25f9157ac5bd (patch)
treebd3a856bd18421306a01d8e9c357e07c06350786
parent0ac0903075e4015f83bbc41577397d0ef86f623b (diff)
Grab the vnode lock in vn_seek(). Consensus has emerged around using the
existing vnode lock to protect writes to the f_offset field of struct file. As opposed of introducing a new lock which turned out to be harder than anticipated. ok mpi@ visa@
-rw-r--r--sys/kern/vfs_vnops.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 5e3673eedf6..62b1099f9fd 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.101 2019/07/12 13:56:27 solene Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.102 2019/07/21 08:30:34 anton Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -602,10 +602,14 @@ vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
struct vnode *vp = fp->f_data;
struct vattr vattr;
off_t newoff;
- int error, special;
+ int error = 0;
+ int special;
if (vp->v_type == VFIFO)
return (ESPIPE);
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
if (vp->v_type == VCHR)
special = 1;
else
@@ -618,21 +622,25 @@ vn_seek(struct file *fp, off_t *offset, int whence, struct proc *p)
case SEEK_END:
error = VOP_GETATTR(vp, &vattr, cred, p);
if (error)
- return (error);
+ goto out;
newoff = *offset + (off_t)vattr.va_size;
break;
case SEEK_SET:
newoff = *offset;
break;
default:
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
- if (!special) {
- if (newoff < 0)
- return(EINVAL);
+ if (!special && newoff < 0) {
+ error = EINVAL;
+ goto out;
}
fp->f_offset = *offset = newoff;
- return (0);
+
+out:
+ VOP_UNLOCK(vp);
+ return (error);
}
/*