From e23485a5fa4ee8679a681c1dead71f925f14965f Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 7 Aug 2009 17:35:36 -0700 Subject: [PATCH] DEVFS - Add required vget when disassociating a vnode from a node. * We have to protect the vnode when disconnecting the rdev and disassociating it from the devfs_node. * This also has the side effect of properly cycling the vnode refs so the namecache gets cleaned up when a node is removed. Otherwise the namecache entry will be left intact, resolved to the now dead vnode. --- sys/vfs/devfs/devfs_core.c | 9 ++++++++- sys/vfs/devfs/devfs_vnops.c | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 552cd9ddc6..955cb845e6 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -390,11 +390,18 @@ devfs_freep(struct devfs_node *node) /* * Disassociate the vnode from the node. This also prevents the * vnode's reclaim code from double-freeing the node. + * + * The vget is needed to safely modify the vp. It also serves + * to cycle the refs and terminate the vnode if it happens to + * be inactive, otherwise namecache references may not get cleared. */ - if ((vp = node->v_node) != NULL) { + while ((vp = node->v_node) != NULL) { + if (vget(vp, LK_EXCLUSIVE | LK_RETRY) != 0) + break; v_release_rdev(vp); vp->v_data = NULL; node->v_node = NULL; + vput(vp); } if (node->d_dir.d_name) kfree(node->d_dir.d_name, M_DEVFS); diff --git a/sys/vfs/devfs/devfs_vnops.c b/sys/vfs/devfs/devfs_vnops.c index 898fb3475a..453616e86b 100644 --- a/sys/vfs/devfs/devfs_vnops.c +++ b/sys/vfs/devfs/devfs_vnops.c @@ -420,6 +420,7 @@ devfs_nresolve(struct vop_nresolve_args *ap) lockmgr(&devfs_lock, LK_EXCLUSIVE); if ((dnode->node_type != Proot) && (dnode->node_type != Pdir)) { + error = ENOENT; cache_setvp(ap->a_nch, NULL); goto out; } -- 2.41.0