sys/vfs/union/union_vnops.c
static int
union_open(struct vop_open_args *ap)
{
	struct union_node *un = VTOUNION(ap->a_vp);
	struct vnode *tvp;
	int mode = ap->a_mode;
	struct ucred *cred = ap->a_cred;
	struct thread *td = ap->a_td;
	int error = 0;
	int tvpisupper = 1;

	/*
	 * If there is an existing upper vp then simply open that.
	 * The upper vp takes precedence over the lower vp.  When opening
	 * a lower vp for writing copy it to the uppervp and then open the
	 * uppervp.
	 *
	 * At the end of this section tvp will be left locked.
	 */
	if ((tvp = union_lock_upper(un, td)) == NULLVP) {
		/*
		 * If the lower vnode is being opened for writing, then
		 * copy the file contents to the upper vnode and open that,
		 * otherwise can simply open the lower vnode.
		 */
		tvp = un->un_lowervp;
		if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
			int docopy = !(mode & O_TRUNC);
			error = union_copyup(un, docopy, cred, td);
			tvp = union_lock_upper(un, td);
		} else {
			un->un_openl++;
			vref(tvp);
			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
			tvpisupper = 0;
		}
	}

	/*
	 * We are holding the correct vnode, open it.  Note
	 * that in DragonFly, VOP_OPEN is responsible for associating
	 * a VM object with the vnode if the vnode is mappable or the
	 * underlying filesystem uses buffer cache calls on it.
	 */
	if (error == 0)
		error = VOP_OPEN(tvp, mode, cred, NULL);

	/*
	 * Release any locks held
	 */
	if (tvpisupper) {
		if (tvp)
			union_unlock_upper(tvp, td);
	} else {
		vput(tvp);
	}
	return (error);
}
/*
 *	union_open:
 *
 *	run open VOP.  When opening the underlying vnode we have to mimic
 *	vn_open.  What we *really* need to do to avoid screwups if the
 *	open semantics change is to call vn_open().  For example, ufs blows
 *	up if you open a file but do not vmio it prior to writing.
 *
 * union_open(struct vnode *a_vp, int a_mode,
 *	      struct ucred *a_cred, struct thread *a_td)
 */
run open VOP.  When opening the underlying vnode we have to mimic
vn_open.  What we *really* need to do to avoid screwups if the
open semantics change is to call vn_open().  For example, ufs blows
up if you open a file but do not vmio it prior to writing.


run open VOP . When opening the underlying vnode we have to mimic vn_open . What we * really * need to do to avoid screwups if the open semantics change is to call vn_open () . For example ufs blows up if you open a file but do not vmio it prior to writing .
static int
union_open(struct vop_open_args *ap)
{
	struct union_node *un = VTOUNION(ap->a_vp);
	struct vnode *tvp;
	int mode = ap->a_mode;
	struct ucred *cred = ap->a_cred;
	struct thread *td = ap->a_td;
	int error = 0;
	int tvpisupper = 1;
	if ((tvp = union_lock_upper(un, td)) == NULLVP) {
		tvp = un->un_lowervp;
		if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
			int docopy = !(mode & O_TRUNC);
			error = union_copyup(un, docopy, cred, td);
			tvp = union_lock_upper(un, td);
		} else {
			un->un_openl++;
			vref(tvp);
			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
			tvpisupper = 0;
		}
	}
	if (error == 0)
		error = VOP_OPEN(tvp, mode, cred, NULL);
	if (tvpisupper) {
		if (tvp)
			union_unlock_upper(tvp, td);
	} else {
		vput(tvp);
	}
	return (error);
}
static int union_open ( struct vop_open_args * ap ) { struct union_node * un = VTOUNION ( ap -> a_vp ) ; struct vnode * tvp ; int mode = ap -> a_mode ; struct ucred * cred = ap -> a_cred ; struct thread * td = ap -> a_td ; int error = 0 ; int tvpisupper = 1 ; if ( ( tvp = union_lock_upper ( un , td ) ) == NULLVP ) { tvp = un -> un_lowervp ; if ( ( ap -> a_mode & FWRITE ) && ( tvp -> v_type == VREG ) ) { int docopy = ! ( mode & O_TRUNC ) ; error = union_copyup ( un , docopy , cred , td ) ; tvp = union_lock_upper ( un , td ) ; } else { un -> un_openl ++ ; vref ( tvp ) ; vn_lock ( tvp , LK_EXCLUSIVE | LK_RETRY ) ; tvpisupper = 0 ; } } if ( error == 0 ) error = VOP_OPEN ( tvp , mode , cred , NULL ) ; if ( tvpisupper ) { if ( tvp ) union_unlock_upper ( tvp , td ) ; } else { vput ( tvp ) ; } return ( error ) ; }
union_open:
      run open VOP.
union_open : run open VOP .
/*
	 * If there is an existing upper vp then simply open that.
	 * The upper vp takes precedence over the lower vp.  When opening
	 * a lower vp for writing copy it to the uppervp and then open the
	 * uppervp.
	 *
	 * At the end of this section tvp will be left locked.
	 */ /*
		 * If the lower vnode is being opened for writing, then
		 * copy the file contents to the upper vnode and open that,
		 * otherwise can simply open the lower vnode.
		 */ /*
	 * We are holding the correct vnode, open it.  Note
	 * that in DragonFly, VOP_OPEN is responsible for associating
	 * a VM object with the vnode if the vnode is mappable or the
	 * underlying filesystem uses buffer cache calls on it.
	 */ /*
	 * Release any locks held
	 */