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