Module Name:    src
Committed By:   hannken
Date:           Tue Oct 18 09:22:53 UTC 2011

Modified Files:
        src/sys/fs/union: union_subr.c union_vnops.c

Log Message:
VOP_GETATTR() needs a shared lock at least.


To generate a diff of this commit:
cvs rdiff -u -r1.50 -r1.51 src/sys/fs/union/union_subr.c
cvs rdiff -u -r1.46 -r1.47 src/sys/fs/union/union_vnops.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.50 src/sys/fs/union/union_subr.c:1.51
--- src/sys/fs/union/union_subr.c:1.50	Tue Aug 23 07:39:37 2011
+++ src/sys/fs/union/union_subr.c	Tue Oct 18 09:22:53 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.50 2011/08/23 07:39:37 hannken Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.51 2011/10/18 09:22:53 hannken Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.50 2011/08/23 07:39:37 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.51 2011/10/18 09:22:53 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -472,9 +472,13 @@ loop:
 	if (uppervp != NULLVP)
 		if (VOP_GETATTR(uppervp, &va, FSCRED) == 0)
 			uppersz = va.va_size;
-	if (lowervp != NULLVP)
-		if (VOP_GETATTR(lowervp, &va, FSCRED) == 0)
+	if (lowervp != NULLVP) {
+		vn_lock(lowervp, LK_SHARED | LK_RETRY);
+		error = VOP_GETATTR(lowervp, &va, FSCRED);
+		VOP_UNLOCK(lowervp);
+		if (error == 0)
 			lowersz = va.va_size;
+	}
 	hash = UNION_HASH(uppervp, lowervp);
 
 	/*
@@ -1213,18 +1217,16 @@ union_readdirhook(struct vnode **vpp, st
 	if (vp->v_op != union_vnodeop_p)
 		return (0);
 
-	if ((lvp = union_dircache(vp, l)) == NULLVP)
-		return (0);
-
 	/*
 	 * If the directory is opaque,
 	 * then don't show lower entries
 	 */
 	error = VOP_GETATTR(vp, &va, fp->f_cred);
-	if (error || (va.va_flags & OPAQUE)) {
-		vput(lvp);
-		return (error);
-	}
+	if (error || (va.va_flags & OPAQUE))
+		return error;
+
+	if ((lvp = union_dircache(vp, l)) == NULLVP)
+		return (0);
 
 	error = VOP_OPEN(lvp, FREAD, fp->f_cred);
 	if (error) {

Index: src/sys/fs/union/union_vnops.c
diff -u src/sys/fs/union/union_vnops.c:1.46 src/sys/fs/union/union_vnops.c:1.47
--- src/sys/fs/union/union_vnops.c:1.46	Tue Aug 23 07:39:37 2011
+++ src/sys/fs/union/union_vnops.c	Tue Oct 18 09:22:53 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_vnops.c,v 1.46 2011/08/23 07:39:37 hannken Exp $	*/
+/*	$NetBSD: union_vnops.c,v 1.47 2011/10/18 09:22:53 hannken Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.46 2011/08/23 07:39:37 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.47 2011/10/18 09:22:53 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -830,14 +830,6 @@ union_getattr(void *v)
 
 	vp = un->un_uppervp;
 	if (vp != NULLVP) {
-		/*
-		 * It's not clear whether VOP_GETATTR is to be
-		 * called with the vnode locked or not.  stat() calls
-		 * it with (vp) locked, and fstat calls it with
-		 * (vp) unlocked.
-		 * In the mean time, compensate here by checking
-		 * the union_node's lock flag.
-		 */
 		if (un->un_flags & UN_LOCKED)
 			FIXUP(un);
 
@@ -858,7 +850,11 @@ union_getattr(void *v)
 	}
 
 	if (vp != NULLVP) {
+		if (vp == un->un_lowervp)
+			vn_lock(vp, LK_SHARED | LK_RETRY);
 		error = VOP_GETATTR(vp, vap, ap->a_cred);
+		if (vp == un->un_lowervp)
+			VOP_UNLOCK(vp);
 		if (error)
 			return (error);
 		union_newsize(ap->a_vp, VNOVAL, vap->va_size);

Reply via email to