Index: sys/fs/unionfs/union_subr.c =================================================================== --- sys/fs/unionfs/union_subr.c (revision 242183) +++ sys/fs/unionfs/union_subr.c (working copy) @@ -237,7 +237,9 @@ unionfs_nodeget(struct mount *mp, struct vnode *up if (vp != NULLVP) { vref(vp); *vpp = vp; - goto unionfs_nodeget_out; + if (lkflags & LK_TYPE_MASK) + lockmgr(vp->v_vnlock, lkflags, NULL); + return (0); } } @@ -255,17 +257,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 +290,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 +328,11 @@ 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); - + if (lkflags & LK_TYPE_MASK) { + if (lkflags == LK_SHARED)) + vn_lock(vp, LK_DOWNGRADE | LK_RETRY); + } else + VOP_UNLOCK(vp, LK_RELEASE); return (0); }