Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern redo vfs_lookup.c rev.1.126.
details: https://anonhg.NetBSD.org/src/rev/1171e22008de
branches: trunk
changeset: 769161:1171e22008de
user: yamt <yamt%NetBSD.org@localhost>
date: Thu Sep 01 15:31:27 2011 +0000
description:
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.
diffstat:
sys/kern/vfs_lookup.c | 48 ++++++++++++++++++++++++++++++++++++------------
1 files changed, 36 insertions(+), 12 deletions(-)
diffs (92 lines):
diff -r 8e9f83d6bcc2 -r 1171e22008de sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c Thu Sep 01 15:15:06 2011 +0000
+++ b/sys/kern/vfs_lookup.c Thu Sep 01 15:31:27 2011 +0000
@@ -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;
}
Home |
Main Index |
Thread Index |
Old Index