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],