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);