Index: sys/fs/unionfs/union_subr.c =================================================================== --- sys/fs/unionfs/union_subr.c (revision 242183) +++ sys/fs/unionfs/union_subr.c (working copy) @@ -213,12 +213,10 @@ unionfs_nodeget(struct mount *mp, struct vnode *up struct unionfs_node *unp; struct vnode *vp; int error; - int lkflags; enum vtype vt; char *path; ump = MOUNTTOUNIONFSMOUNT(mp); - lkflags = (cnp ? cnp->cn_lkflags : 0); path = (cnp ? cnp->cn_nameptr : NULL); *vpp = NULLVP; @@ -237,7 +235,8 @@ unionfs_nodeget(struct mount *mp, struct vnode *up if (vp != NULLVP) { vref(vp); *vpp = vp; - goto unionfs_nodeget_out; + lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); + return (0); } } @@ -255,17 +254,19 @@ unionfs_nodeget(struct mount *mp, struct vnode *up */ unp = malloc(sizeof(struct unionfs_node), M_UNIONFSNODE, M_WAITOK | M_ZERO); + if (path != NULL) { + unp->un_path = (char *) + malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO); + bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen); + unp->un_path[cnp->cn_namelen] = '\0'; + } error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp); if (error != 0) { + free(unp->un_path, M_UNIONFSNODE); free(unp, M_UNIONFSNODE); return (error); } - error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */ - if (error != 0) { - free(unp, M_UNIONFSNODE); - return (error); - } if (dvp != NULLVP) vref(dvp); if (uppervp != NULLVP) @@ -286,15 +287,22 @@ unionfs_nodeget(struct mount *mp, struct vnode *up else vp->v_vnlock = lowervp->v_vnlock; - if (path != NULL) { - unp->un_path = (char *) - malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO); - bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen); - unp->un_path[cnp->cn_namelen] = '\0'; - } vp->v_type = vt; vp->v_data = unp; + lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); + error = insmntque(vp, mp); + if (error != 0) { + if (dvp != NULLVP) + vrele(dvp); + if (uppervp != NULLVP) + vrele(uppervp); + if (lowervp != NULLVP) + vrele(lowervp); + free(unp->un_path, M_UNIONFSNODE); + free(unp, M_UNIONFSNODE); + return (error); + } if ((uppervp != NULLVP && ump->um_uppervp == uppervp) && (lowervp != NULLVP && ump->um_lowervp == lowervp)) vp->v_vflag |= VV_ROOT; @@ -317,11 +325,6 @@ unionfs_nodeget(struct mount *mp, struct vnode *up vref(vp); } else *vpp = vp; - -unionfs_nodeget_out: - if (lkflags & LK_TYPE_MASK) - vn_lock(vp, lkflags | LK_RETRY); - return (0); } Index: sys/fs/unionfs/union_vnops.c =================================================================== --- sys/fs/unionfs/union_vnops.c (revision 242183) +++ sys/fs/unionfs/union_vnops.c (working copy) @@ -79,7 +79,6 @@ static int unionfs_lookup(struct vop_cachedlookup_args *ap) { int iswhiteout; - int lockflag; int error , uerror, lerror; u_long nameiop; u_long cnflags, cnflagsbk; @@ -90,7 +89,6 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) struct thread *td; iswhiteout = 0; - lockflag = 0; error = uerror = lerror = ENOENT; cnp = ap->a_cnp; nameiop = cnp->cn_nameiop; @@ -265,26 +263,15 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) if (error != 0) goto unionfs_lookup_out; - if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK)) - VOP_UNLOCK(vp, LK_RELEASE); - if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) { - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - lockflag = 1; - } error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount), udvp, VTOUNIONFS(vp), cnp, td); - if (lockflag != 0) - VOP_UNLOCK(vp, LK_RELEASE); if (error != 0) { UNIONFSDEBUG("unionfs_lookup: Unable to create shadow dir."); - if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) - vput(vp); - else - vrele(vp); + vput(vp); goto unionfs_lookup_out; } if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED) - vn_lock(vp, LK_SHARED | LK_RETRY); + vn_lock(vp, LK_DOWNGRADE | LK_RETRY); } /* * get unionfs vnode. @@ -321,9 +308,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) UNIONFSDEBUG("unionfs_lookup: Unable to create unionfs vnode."); goto unionfs_lookup_out; } - if ((nameiop == DELETE || nameiop == RENAME) && - (cnp->cn_lkflags & LK_TYPE_MASK) == 0) - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + ASSERT_VOP_ELOCKED(vp, __func__); } *(ap->a_vpp) = vp; @@ -1329,7 +1314,6 @@ static int unionfs_mkdir(struct vop_mkdir_args *ap) { int error; - int lkflags; struct unionfs_node *dunp; struct componentname *cnp; struct thread *td; @@ -1344,7 +1328,6 @@ unionfs_mkdir(struct vop_mkdir_args *ap) error = EROFS; dunp = VTOUNIONFS(ap->a_dvp); cnp = ap->a_cnp; - lkflags = cnp->cn_lkflags; td = curthread; udvp = dunp->un_uppervp; @@ -1360,10 +1343,8 @@ unionfs_mkdir(struct vop_mkdir_args *ap) if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { VOP_UNLOCK(uvp, LK_RELEASE); - cnp->cn_lkflags = LK_EXCLUSIVE; error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, ap->a_dvp, ap->a_vpp, cnp, td); - cnp->cn_lkflags = lkflags; vrele(uvp); } } @@ -1436,7 +1417,6 @@ static int unionfs_symlink(struct vop_symlink_args *ap) { int error; - int lkflags; struct unionfs_node *dunp; struct componentname *cnp; struct thread *td; @@ -1450,7 +1430,6 @@ unionfs_symlink(struct vop_symlink_args *ap) error = EROFS; dunp = VTOUNIONFS(ap->a_dvp); cnp = ap->a_cnp; - lkflags = cnp->cn_lkflags; td = curthread; udvp = dunp->un_uppervp; @@ -1458,10 +1437,8 @@ unionfs_symlink(struct vop_symlink_args *ap) error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); if (error == 0) { VOP_UNLOCK(uvp, LK_RELEASE); - cnp->cn_lkflags = LK_EXCLUSIVE; error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, ap->a_dvp, ap->a_vpp, cnp, td); - cnp->cn_lkflags = lkflags; vrele(uvp); } }