summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-07-23 19:07:32 +0000
committeranton <anton@cvs.openbsd.org>2019-07-23 19:07:32 +0000
commit69bb9f8a2169b48401564a134465e1c05f2af188 (patch)
tree8b5d9acb8b5523acafc29aadc58e88b89236cffa /sys
parent65fd19754520890eee46e2008b4a27776fab4020 (diff)
Grab the vnode lock earlier in vn_read() since it could end up sleeping,
allowing the file offset to change. This is part of the ongoing effort to protect the file offset using the vnode lock. ok mpi@ visa@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_vnops.c15
1 files changed, 5 insertions, 10 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 62b1099f9fd..c829aa20f07 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.102 2019/07/21 08:30:34 anton Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.103 2019/07/23 19:07:31 anton Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -345,12 +345,10 @@ vn_read(struct file *fp, struct uio *uio, int fflags)
KERNEL_LOCK();
- /*
- * Check below can race. We can block on the vnode lock
- * and resume with a different `fp->f_offset' value.
- */
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
if ((fflags & FO_POSITION) == 0)
- offset = fp->f_offset;
+ offset = uio->uio_offset = fp->f_offset;
else
offset = uio->uio_offset;
@@ -365,15 +363,12 @@ vn_read(struct file *fp, struct uio *uio, int fflags)
goto done;
}
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if ((fflags & FO_POSITION) == 0)
- uio->uio_offset = fp->f_offset;
error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
cred);
if ((fflags & FO_POSITION) == 0)
fp->f_offset += count - uio->uio_resid;
- VOP_UNLOCK(vp);
done:
+ VOP_UNLOCK(vp);
KERNEL_UNLOCK();
return (error);
}