From: Matthew Dillon Date: Thu, 1 Dec 2011 23:22:44 +0000 (-0800) Subject: kernel - Fix lost lock in devfs X-Git-Tag: v3.0.0~514 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/495d3a1efd4f8832641e3489717539bbe8d72ebe kernel - Fix lost lock in devfs * vn_lock() will always fail if a vnode is undergoing reclamation, do not try to unlock/relock in the spec_close code in that case. * Refactor the error test in devfs_allocv() in case vget() returns an error other than ENOENT in the future. --- diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 8fd9992..8e4d9b8 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -295,10 +295,14 @@ devfs_allocv(struct vnode **vpp, struct devfs_node *node) try_again: while ((vp = node->v_node) != NULL) { error = vget(vp, LK_EXCLUSIVE); - if (error != ENOENT) { + if (error == 0) { *vpp = vp; goto out; } + if (error != ENOENT) { + *vpp = NULL; + goto out; + } } if ((error = getnewvnode(VT_DEVFS, node->mp, vpp, 0, 0)) != 0) diff --git a/sys/vfs/devfs/devfs_vnops.c b/sys/vfs/devfs/devfs_vnops.c index dcc88fd..04638fb 100644 --- a/sys/vfs/devfs/devfs_vnops.c +++ b/sys/vfs/devfs/devfs_vnops.c @@ -1062,10 +1062,11 @@ devfs_spec_close(struct vop_close_args *ap) node->flags |= DEVFS_INVISIBLE; /* - * Unlock around dev_dclose() + * Unlock around dev_dclose(), unless the vnode is + * undergoing a vgone/reclaim (during umount). */ needrelock = 0; - if (vn_islocked(vp)) { + if ((vp->v_flag & VRECLAIMED) == 0 && vn_islocked(vp)) { needrelock = 1; vn_unlock(vp); } @@ -1073,12 +1074,20 @@ devfs_spec_close(struct vop_close_args *ap) /* * WARNING! If the device destroys itself the devfs node * can disappear here. + * + * WARNING! vn_lock() will fail if the vp is in a VRECLAIM, + * which can occur during umount. */ error = dev_dclose(dev, ap->a_fflag, S_IFCHR); /* node is now stale */ - if (needrelock) - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (needrelock) { + if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY) != 0) { + panic("devfs_spec_close: vnode %p " + "unexpectedly could not be relocked", + vp); + } + } } else { error = 0; }