summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2013-10-29 03:11:08 +0000
committerguenther <guenther@openbsd.org>2013-10-29 03:11:08 +0000
commit74755ccae08f64aaa251bfca098ed4ba7e8a6fe5 (patch)
treec6122b1c5bc113ddea7c84ea48e6363faf18b145
parentino_t is 64 bit now (diff)
downloadwireguard-openbsd-74755ccae08f64aaa251bfca098ed4ba7e8a6fe5.tar.xz
wireguard-openbsd-74755ccae08f64aaa251bfca098ed4ba7e8a6fe5.zip
Unlock the vnode while calling a device's d_close routine, except when
it's locked for changing the type (i.e., revoke()). We already unlock it while calling the d_open, d_read, and d_write routines and this is safe for the same reason: the device routines operate at a lower level and don't need the protection of the vnode locks. This is important as the device close routine may block indefinitely. "don't see anything wrong" tedu@
-rw-r--r--sys/kern/spec_vnops.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c
index 20ce5f2da03..69873142961 100644
--- a/sys/kern/spec_vnops.c
+++ b/sys/kern/spec_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spec_vnops.c,v 1.76 2013/08/06 08:22:37 kettenis Exp $ */
+/* $OpenBSD: spec_vnops.c,v 1.77 2013/10/29 03:11:08 guenther Exp $ */
/* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
/*
@@ -472,10 +472,11 @@ int
spec_close(void *v)
{
struct vop_close_args *ap = v;
+ struct proc *p = ap->a_p;
struct vnode *vp = ap->a_vp;
dev_t dev = vp->v_rdev;
int (*devclose)(dev_t, int, int, struct proc *);
- int mode, error;
+ int mode, relock, error;
switch (vp->v_type) {
@@ -541,7 +542,14 @@ spec_close(void *v)
panic("spec_close: not special");
}
- return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
+ /* release lock if held and this isn't coming from vclean() */
+ relock = VOP_ISLOCKED(vp) && !(vp->v_flag & VXLOCK);
+ if (relock)
+ VOP_UNLOCK(vp, 0, p);
+ error = (*devclose)(dev, ap->a_fflag, mode, p);
+ if (relock)
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ return (error);
}
int