summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_subr.c5
-rw-r--r--sys/kern/vfs_vnops.c20
-rw-r--r--sys/kern/vfs_vops.c14
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));
}