diff options
author | anton <anton@cvs.openbsd.org> | 2019-07-21 08:30:35 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-07-21 08:30:35 +0000 |
commit | efc8fe3631b3dcc5853f0c28164f25f9157ac5bd (patch) | |
tree | bd3a856bd18421306a01d8e9c357e07c06350786 | |
parent | 0ac0903075e4015f83bbc41577397d0ef86f623b (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.c | 24 |
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); } /* |