Module Name: src Committed By: hannken Date: Fri Nov 25 11:19:10 UTC 2011
Modified Files: src/sys/fs/union: union_subr.c Log Message: When union_allocvp() finds a node being cleaned out and the caller holds a lock, ignore the node and continue. To allow the cleaning to succeed the current threadmust make progress. For a brief time the cache may contain more than one vnode referring to a lower node. Don't unlock the hash mutex if getnewvnode fails -- we don't hold it. To generate a diff of this commit: cvs rdiff -u -r1.54 -r1.55 src/sys/fs/union/union_subr.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/fs/union/union_subr.c diff -u src/sys/fs/union/union_subr.c:1.54 src/sys/fs/union/union_subr.c:1.55 --- src/sys/fs/union/union_subr.c:1.54 Wed Nov 23 19:39:11 2011 +++ src/sys/fs/union/union_subr.c Fri Nov 25 11:19:10 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: union_subr.c,v 1.54 2011/11/23 19:39:11 hannken Exp $ */ +/* $NetBSD: union_subr.c,v 1.55 2011/11/25 11:19:10 hannken Exp $ */ /* * Copyright (c) 1994 @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.54 2011/11/23 19:39:11 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.55 2011/11/25 11:19:10 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -404,6 +404,18 @@ loop: lflag = LK_EXCLUSIVE; vp = UNIONTOV(un); mutex_enter(vp->v_interlock); + /* + * If this node being cleaned out and our caller + * holds a lock, then ignore it and continue. To + * allow the cleaning to succeed the current thread + * must make progress. For a brief time the cache + * may contain more than one vnode referring to + * a lower node. + */ + if ((vp->v_iflag & VI_XLOCK) != 0 && lflag == 0) { + mutex_exit(vp->v_interlock); + continue; + } mutex_exit(&uhash_lock); if (vget(vp, lflag)) goto loop; @@ -484,7 +496,7 @@ found: if (lowervp) vrele(lowervp); - goto out; + return error; } if (docache) { @@ -493,6 +505,17 @@ found: if (un1->un_lowervp == lowervp && un1->un_uppervp == uppervp && UNIONTOV(un1)->v_mount == mp) { + vp = UNIONTOV(un1); + mutex_enter(vp->v_interlock); + /* + * Ignore nodes being cleaned out. + * See the cache lookup above. + */ + if ((vp->v_iflag & VI_XLOCK) != 0) { + mutex_exit(vp->v_interlock); + continue; + } + mutex_exit(vp->v_interlock); /* * Another thread beat us, push back freshly * allocated vnode and retry. @@ -569,7 +592,6 @@ found: if (xlowervp) vrele(xlowervp); -out: if (docache) mutex_exit(&uhash_lock);