diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_subr.c | 5 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 20 | ||||
-rw-r--r-- | sys/kern/vfs_vops.c | 14 |
3 files changed, 34 insertions, 5 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 5a67cd31b28..64de71d0680 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.292 2019/07/25 01:43:21 cheloha Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.293 2019/08/26 18:56:29 anton Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -705,6 +705,9 @@ vputonfreelist(struct vnode *vp) if (vp->v_usecount != 0) panic("Use count is not zero!"); + if (vp->v_lockcount != 0) + panic("%s: lock count is not zero", __func__); + if (vp->v_bioflag & VBIOONFREELIST) { vprint("vnode already on free list: ", vp); panic("vnode already on free list"); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index a2f481ce6b8..353fc7a3feb 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vnops.c,v 1.106 2019/08/13 07:09:21 anton Exp $ */ +/* $OpenBSD: vfs_vnops.c,v 1.107 2019/08/26 18:56:29 anton Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* @@ -558,9 +558,23 @@ vn_lock(struct vnode *vp, int flags) tsleep(vp, PINOD, "vn_lock", 0); error = ENOENT; } else { + vp->v_lockcount++; error = VOP_LOCK(vp, flags); - if (error == 0) - return (error); + vp->v_lockcount--; + if (error == 0) { + if ((vp->v_flag & VXLOCK) == 0) + return (0); + + /* + * The vnode was exclusively locked while + * acquiring the requested lock. Release it and + * try again. + */ + error = ENOENT; + VOP_UNLOCK(vp); + if (vp->v_lockcount == 0) + wakeup_one(&vp->v_lockcount); + } } } while (flags & LK_RETRY); return (error); diff --git a/sys/kern/vfs_vops.c b/sys/kern/vfs_vops.c index 9c39ab07705..e606c0b8af7 100644 --- a/sys/kern/vfs_vops.c +++ b/sys/kern/vfs_vops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vops.c,v 1.21 2019/05/03 14:24:13 visa Exp $ */ +/* $OpenBSD: vfs_vops.c,v 1.22 2019/08/26 18:56:29 anton Exp $ */ /* * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> * @@ -46,6 +46,7 @@ #include <sys/vnode.h> #include <sys/unistd.h> #include <sys/systm.h> +#include <sys/lock.h> /* LK_DRAIN */ #ifdef VFSLCKDEBUG #include <sys/systm.h> /* for panic() */ @@ -599,6 +600,17 @@ VOP_LOCK(struct vnode *vp, int flags) if (vp->v_op->vop_lock == NULL) return (EOPNOTSUPP); + if ((flags & LK_DRAIN) && vp->v_lockcount > 0) { + /* + * Ensure that any thread currently waiting on the same lock has + * observed that the vnode is about to be exclusively locked + * before continuing. + */ + KASSERT(vp->v_flag & VXLOCK); + tsleep(&vp->v_lockcount, PINOD, "vop_lock", 0); + KASSERT(vp->v_lockcount == 0); + } + return ((vp->v_op->vop_lock)(&a)); } |