diff options
author | anton <anton@cvs.openbsd.org> | 2019-07-23 19:07:32 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-07-23 19:07:32 +0000 |
commit | 69bb9f8a2169b48401564a134465e1c05f2af188 (patch) | |
tree | 8b5d9acb8b5523acafc29aadc58e88b89236cffa /sys | |
parent | 65fd19754520890eee46e2008b4a27776fab4020 (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.c | 15 |
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); } |