sys/vfs/union/union_vnops.c
static int
union_getattr(struct vop_getattr_args *ap)
{
	int error;
	struct union_node *un = VTOUNION(ap->a_vp);
	struct vnode *vp;
	struct vattr *vap;
	struct vattr va;

	/*
	 * Some programs walk the filesystem hierarchy by counting
	 * links to directories to avoid stat'ing all the time.
	 * This means the link count on directories needs to be "correct".
	 * The only way to do that is to call getattr on both layers
	 * and fix up the link count.  The link count will not necessarily
	 * be accurate but will be large enough to defeat the tree walkers.
	 */

	vap = ap->a_vap;

	if ((vp = un->un_uppervp) != NULLVP) {
		error = VOP_GETATTR(vp, vap);
		if (error)
			return (error);
		/* XXX isn't this dangerouso without a lock? */
		union_newsize(ap->a_vp, vap->va_size, VNOVAL);
	}

	if (vp == NULLVP) {
		vp = un->un_lowervp;
	} else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
		vp = un->un_lowervp;
		vap = &va;
	} else {
		vp = NULLVP;
	}

	if (vp != NULLVP) {
		error = VOP_GETATTR(vp, vap);
		if (error)
			return (error);
		/* XXX isn't this dangerous without a lock? */
		union_newsize(ap->a_vp, VNOVAL, vap->va_size);
	}

	if ((vap != ap->a_vap) && (vap->va_type == VDIR))
		ap->a_vap->va_nlink += vap->va_nlink;
	return (0);
}
/*
 * We handle getattr only to change the fsid and
 * track object sizes
 *
 * 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. 
 *
 * Because of this we cannot use our normal locking functions
 * if we do not intend to lock the main a_vp node.  At the moment
 * we are running without any specific locking at all, but beware
 * to any programmer that care must be taken if locking is added
 * to this function.
 *
 * union_getattr(struct vnode *a_vp, struct vattr *a_vap,
 *		 struct ucred *a_cred, struct thread *a_td)
 */
We handle getattr only to change the fsid and
track object sizes

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.

Because of this we cannot use our normal locking functions
if we do not intend to lock the main a_vp node.  At the moment
we are running without any specific locking at all, but beware
to any programmer that care must be taken if locking is added
to this function.


We handle getattr only to change the fsid and track object sizes 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 . Because of this we cannot use our normal locking functions if we do not intend to lock the main a_vp node . At the moment we are running without any specific locking at all but beware to any programmer that care must be taken if locking is added to this function .
static int
union_getattr(struct vop_getattr_args *ap)
{
	int error;
	struct union_node *un = VTOUNION(ap->a_vp);
	struct vnode *vp;
	struct vattr *vap;
	struct vattr va;
	vap = ap->a_vap;
	if ((vp = un->un_uppervp) != NULLVP) {
		error = VOP_GETATTR(vp, vap);
		if (error)
			return (error);
		union_newsize(ap->a_vp, vap->va_size, VNOVAL);
	}
	if (vp == NULLVP) {
		vp = un->un_lowervp;
	} else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
		vp = un->un_lowervp;
		vap = &va;
	} else {
		vp = NULLVP;
	}
	if (vp != NULLVP) {
		error = VOP_GETATTR(vp, vap);
		if (error)
			return (error);
		union_newsize(ap->a_vp, VNOVAL, vap->va_size);
	}
	if ((vap != ap->a_vap) && (vap->va_type == VDIR))
		ap->a_vap->va_nlink += vap->va_nlink;
	return (0);
}
static int union_getattr ( struct vop_getattr_args * ap ) { int error ; struct union_node * un = VTOUNION ( ap -> a_vp ) ; struct vnode * vp ; struct vattr * vap ; struct vattr va ; vap = ap -> a_vap ; if ( ( vp = un -> un_uppervp ) != NULLVP ) { error = VOP_GETATTR ( vp , vap ) ; if ( error ) return ( error ) ; union_newsize ( ap -> a_vp , vap -> va_size , VNOVAL ) ; } if ( vp == NULLVP ) { vp = un -> un_lowervp ; } else if ( vp -> v_type == VDIR && un -> un_lowervp != NULLVP ) { vp = un -> un_lowervp ; vap = & va ; } else { vp = NULLVP ; } if ( vp != NULLVP ) { error = VOP_GETATTR ( vp , vap ) ; if ( error ) return ( error ) ; union_newsize ( ap -> a_vp , VNOVAL , vap -> va_size ) ; } if ( ( vap != ap -> a_vap ) && ( vap -> va_type == VDIR ) ) ap -> a_vap -> va_nlink += vap -> va_nlink ; return ( 0 ) ; }
We handle getattr only to change the fsid and
 track object sizes
We handle getattr only to change the fsid and track object sizes
/*
	 * Some programs walk the filesystem hierarchy by counting
	 * links to directories to avoid stat'ing all the time.
	 * This means the link count on directories needs to be "correct".
	 * The only way to do that is to call getattr on both layers
	 * and fix up the link count.  The link count will not necessarily
	 * be accurate but will be large enough to defeat the tree walkers.
	 */ /* XXX isn't this dangerouso without a lock? */ /* XXX isn't this dangerous without a lock? */