Module Name: src
Committed By: yamt
Date: Thu Sep 1 15:31:27 UTC 2011
Modified Files:
src/sys/kern: vfs_lookup.c
Log Message:
redo vfs_lookup.c rev.1.126.
when crossing a mount point, don't keep the parent vnode locked.
ie. don't lock a vnode while holding another vnode which belongs to a
different filesystem. otherwise we propagate slowness (or deadness) of a
filesystem to another via vnode lock chain.
To generate a diff of this commit:
cvs rdiff -u -r1.189 -r1.190 src/sys/kern/vfs_lookup.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_lookup.c
diff -u src/sys/kern/vfs_lookup.c:1.189 src/sys/kern/vfs_lookup.c:1.190
--- src/sys/kern/vfs_lookup.c:1.189 Sat Aug 13 19:40:02 2011
+++ src/sys/kern/vfs_lookup.c Thu Sep 1 15:31:27 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_lookup.c,v 1.189 2011/08/13 19:40:02 riastradh Exp $ */
+/* $NetBSD: vfs_lookup.c,v 1.190 2011/09/01 15:31:27 yamt Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.189 2011/08/13 19:40:02 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.190 2011/09/01 15:31:27 yamt Exp $");
#include "opt_magiclinks.h"
@@ -1040,11 +1040,16 @@
(cnp->cn_flags & NOCROSSMOUNT) == 0) {
error = vfs_busy(mp, NULL);
if (error != 0) {
- vput(foundobj);
+ if (searchdir != foundobj) {
+ vput(foundobj);
+ } else {
+ vrele(foundobj);
+ }
goto done;
}
- KASSERT(searchdir != foundobj);
- VOP_UNLOCK(searchdir);
+ if (searchdir != foundobj) {
+ VOP_UNLOCK(searchdir);
+ }
vput(foundobj);
error = VFS_ROOT(mp, &foundobj);
vfs_unbusy(mp, false, NULL);
@@ -1052,9 +1057,22 @@
vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY);
goto done;
}
- VOP_UNLOCK(foundobj);
- vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY);
- vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY);
+ /*
+ * avoid locking vnodes from two filesystems because it's
+ * prune to deadlock. eg. when using puffs.
+ * also, it isn't a good idea to propagate slowness of a
+ * filesystem up to the root directory.
+ * for now, only handle the common case. (ie. foundobj is VDIR)
+ */
+ if (foundobj->v_type == VDIR) {
+ vrele(searchdir);
+ *newsearchdir_ret = searchdir = foundobj;
+ vref(searchdir);
+ } else {
+ VOP_UNLOCK(foundobj);
+ vn_lock(searchdir, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY);
+ }
}
*foundobj_ret = foundobj;
@@ -1240,9 +1258,11 @@
* Check for directory, if the component was
* followed by a series of slashes.
*/
- if ((foundobj->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) {
- KASSERT(foundobj != searchdir);
- if (searchdir) {
+ if ((foundobj->v_type != VDIR) &&
+ (cnp->cn_flags & REQUIREDIR)) {
+ if (searchdir == foundobj) {
+ vrele(searchdir);
+ } else {
vput(searchdir);
}
vput(foundobj);
@@ -1545,7 +1565,11 @@
vref(startdir);
vn_lock(startdir, LK_EXCLUSIVE | LK_RETRY);
error = lookup_once(state, startdir, &startdir, &foundobj);
- vput(startdir);
+ if (error == 0 && startdir == foundobj) {
+ vrele(startdir);
+ } else {
+ vput(startdir);
+ }
if (error) {
goto bad;
}