Module Name: src Committed By: hannken Date: Tue Dec 27 11:59:36 UTC 2016
Modified Files: src/sys/kern: vfs_vnode.c Log Message: It is wrong to block the vnode during vcache_rekey. The vnode may be looked up using the old key until vcache_rekey_exit changes the key to the new one. Add an assertion that the temporary key is different from the current one. To generate a diff of this commit: cvs rdiff -u -r1.64 -r1.65 src/sys/kern/vfs_vnode.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/vfs_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.64 src/sys/kern/vfs_vnode.c:1.65 --- src/sys/kern/vfs_vnode.c:1.64 Tue Dec 20 10:02:21 2016 +++ src/sys/kern/vfs_vnode.c Tue Dec 27 11:59:36 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.64 2016/12/20 10:02:21 hannken Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.65 2016/12/27 11:59:36 hannken Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -156,7 +156,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.64 2016/12/20 10:02:21 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.65 2016/12/27 11:59:36 hannken Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -1305,7 +1305,7 @@ vcache_new(struct mount *mp, struct vnod } /* - * Prepare key change: lock old and new cache node. + * Prepare key change: update old cache nodes key and lock new cache node. * Return an error if the new node already exists. */ int @@ -1345,20 +1345,18 @@ vcache_rekey_enter(struct mount *mp, str SLIST_INSERT_HEAD(&vcache.hashtab[new_hash & vcache.hashmask], new_node, vi_hash); - /* Lock old node. */ + /* Replace old nodes key with the temporary copy. */ node = vcache_hash_lookup(&old_vcache_key, old_hash); KASSERT(node != NULL); KASSERT(VIMPL_TO_VNODE(node) == vp); - mutex_enter(vp->v_interlock); - VSTATE_CHANGE(vp, VS_ACTIVE, VS_BLOCKED); + KASSERT(node->vi_key.vk_key != old_vcache_key.vk_key); node->vi_key = old_vcache_key; - mutex_exit(vp->v_interlock); mutex_exit(&vcache.lock); return 0; } /* - * Key change complete: remove old node and unlock new node. + * Key change complete: update old node and remove placeholder. */ void vcache_rekey_exit(struct mount *mp, struct vnode *vp, @@ -1386,8 +1384,6 @@ vcache_rekey_exit(struct mount *mp, stru old_node = vcache_hash_lookup(&old_vcache_key, old_hash); KASSERT(old_node != NULL); KASSERT(VIMPL_TO_VNODE(old_node) == vp); - mutex_enter(vp->v_interlock); - VSTATE_ASSERT(vp, VS_BLOCKED); new_node = vcache_hash_lookup(&new_vcache_key, new_hash); KASSERT(new_node != NULL); @@ -1404,8 +1400,6 @@ vcache_rekey_exit(struct mount *mp, stru SLIST_INSERT_HEAD(&vcache.hashtab[new_hash & vcache.hashmask], old_node, vi_hash); } - VSTATE_CHANGE(vp, VS_BLOCKED, VS_ACTIVE); - mutex_exit(vp->v_interlock); /* Remove new node used as placeholder. */ SLIST_REMOVE(&vcache.hashtab[new_hash & vcache.hashmask],