diff --git a/sys/fs/unionfs/union.h b/sys/fs/unionfs/union.h --- a/sys/fs/unionfs/union.h +++ b/sys/fs/unionfs/union.h @@ -98,6 +98,7 @@ u_long un_hashmask; /* bit mask */ char *un_path; /* path */ + int un_pathlen; /* strlen of path */ int un_flag; /* unionfs node flag */ }; @@ -124,7 +125,8 @@ void unionfs_create_uppervattr_core(struct unionfs_mount *ump, struct vattr *lva, struct vattr *uva, struct thread *td); int unionfs_create_uppervattr(struct unionfs_mount *ump, struct vnode *lvp, struct vattr *uva, struct ucred *cred, struct thread *td); int unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *duvp, struct unionfs_node *unp, struct componentname *cnp, struct thread *td); -int unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, struct thread *td, char *path); +int unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, + struct thread *td, char *path, int pathlen); int unionfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct componentname *cn, struct thread *td, char *path, int pathlen, u_long nameiop); int unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp, struct thread *td); int unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp, struct thread *td); diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -332,6 +332,7 @@ 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'; + unp->un_pathlen = cnp->cn_namelen; } vp->v_type = vt; vp->v_data = unp; @@ -420,6 +421,7 @@ if (unp->un_path != NULL) { free(unp->un_path, M_UNIONFSPATH); unp->un_path = NULL; + unp->un_pathlen = 0; } if (unp->un_hashtbl != NULL) { @@ -576,16 +578,12 @@ int error; cn->cn_namelen = pathlen; - cn->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); - bcopy(path, cn->cn_pnbuf, pathlen); - cn->cn_pnbuf[pathlen] = '\0'; - + cn->cn_pnbuf = path; cn->cn_nameiop = nameiop; cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN); cn->cn_lkflags = LK_EXCLUSIVE; cn->cn_thread = td; cn->cn_cred = cnp->cn_cred; - cn->cn_nameptr = cn->cn_pnbuf; if (nameiop == DELETE) @@ -599,12 +597,16 @@ VOP_UNLOCK(dvp); if ((error = relookup(dvp, vpp, cn))) { - uma_zfree(namei_zone, cn->cn_pnbuf); - cn->cn_flags &= ~HASBUF; vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); } else vrele(dvp); + KASSERT((cn->cn_flags & HASBUF) != 0, + ("%s: HASBUF cleared", __func__)); + KASSERT((cn->cn_flags & SAVENAME) != 0, + ("%s: SAVENAME cleared", __func__)); + KASSERT(cn->cn_pnbuf == path, ("%s: cn_pnbuf changed", __func__)); + return (error); } @@ -630,7 +632,7 @@ vp = NULLVP; error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, - strlen(cnp->cn_nameptr), CREATE); + cnp->cn_namelen, CREATE); if (error) return (error); @@ -643,16 +645,6 @@ error = EEXIST; } - if (cn.cn_flags & HASBUF) { - uma_zfree(namei_zone, cn.cn_pnbuf); - cn.cn_flags &= ~HASBUF; - } - - if (!error) { - cn.cn_flags |= (cnp->cn_flags & HASBUF); - cnp->cn_flags = cn.cn_flags; - } - return (error); } @@ -674,7 +666,7 @@ vp = NULLVP; error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, - strlen(cnp->cn_nameptr), DELETE); + cnp->cn_namelen, DELETE); if (error) return (error); @@ -687,16 +679,6 @@ vput(vp); } - if (cn.cn_flags & HASBUF) { - uma_zfree(namei_zone, cn.cn_pnbuf); - cn.cn_flags &= ~HASBUF; - } - - if (!error) { - cn.cn_flags |= (cnp->cn_flags & HASBUF); - cnp->cn_flags = cn.cn_flags; - } - return (error); } @@ -718,7 +700,7 @@ vp = NULLVP; error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr, - strlen(cnp->cn_nameptr), RENAME); + cnp->cn_namelen, RENAME); if (error) return (error); @@ -729,18 +711,7 @@ vput(vp); } - if (cn.cn_flags & HASBUF) { - uma_zfree(namei_zone, cn.cn_pnbuf); - cn.cn_flags &= ~HASBUF; - } - - if (!error) { - cn.cn_flags |= (cnp->cn_flags & HASBUF); - cnp->cn_flags = cn.cn_flags; - } - return (error); - } /* @@ -848,11 +819,11 @@ vput(uvp); error = EEXIST; - goto unionfs_mkshadowdir_free_out; + goto unionfs_mkshadowdir_abort; } if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH))) - goto unionfs_mkshadowdir_free_out; + goto unionfs_mkshadowdir_abort; unionfs_create_uppervattr_core(ump, &lva, &va, td); error = VOP_MKDIR(udvp, &uvp, &nd.ni_cnd, &va); @@ -869,12 +840,6 @@ } vn_finished_write(mp); -unionfs_mkshadowdir_free_out: - if (nd.ni_cnd.cn_flags & HASBUF) { - uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); - nd.ni_cnd.cn_flags &= ~HASBUF; - } - unionfs_mkshadowdir_abort: cnp->cn_cred = credbk; chgproccnt(cred->cr_ruidinfo, -1, 0); @@ -890,26 +855,20 @@ */ int unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, - struct thread *td, char *path) + struct thread *td, char *path, int pathlen) { - int error; struct vnode *wvp; struct nameidata nd; struct mount *mp; - - if (path == NULL) - path = cnp->cn_nameptr; + int error; wvp = NULLVP; NDPREINIT(&nd); if ((error = unionfs_relookup(dvp, &wvp, cnp, &nd.ni_cnd, td, path, - strlen(path), CREATE))) + pathlen, CREATE))) { return (error); + } if (wvp != NULLVP) { - if (nd.ni_cnd.cn_flags & HASBUF) { - uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); - nd.ni_cnd.cn_flags &= ~HASBUF; - } if (dvp == wvp) vrele(wvp); else @@ -925,11 +884,6 @@ vn_finished_write(mp); unionfs_mkwhiteout_free_out: - if (nd.ni_cnd.cn_flags & HASBUF) { - uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); - nd.ni_cnd.cn_flags &= ~HASBUF; - } - return (error); } @@ -969,9 +923,8 @@ if (unp->un_path == NULL) panic("unionfs: un_path is null"); - nd.ni_cnd.cn_namelen = strlen(unp->un_path); - nd.ni_cnd.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); - bcopy(unp->un_path, nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_namelen + 1); + nd.ni_cnd.cn_namelen = unp->un_pathlen; + nd.ni_cnd.cn_pnbuf = unp->un_path; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN; @@ -1015,10 +968,12 @@ VOP_UNLOCK(udvp); unionfs_vn_create_on_upper_free_out2: - if (nd.ni_cnd.cn_flags & HASBUF) { - uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); - nd.ni_cnd.cn_flags &= ~HASBUF; - } + KASSERT((nd.ni_cnd.cn_flags & HASBUF) != 0, + ("%s: HASBUF cleared", __func__)); + KASSERT((nd.ni_cnd.cn_flags & SAVENAME) != 0, + ("%s: SAVENAME cleared", __func__)); + KASSERT(nd.ni_cnd.cn_pnbuf == unp->un_path, + ("%s: cn_pnbuf changed", __func__)); return (error); } diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -961,7 +961,6 @@ static int unionfs_remove(struct vop_remove_args *ap) { - int error; char *path; struct unionfs_node *dunp; struct unionfs_node *unp; @@ -973,6 +972,8 @@ struct componentname *cnp; struct componentname cn; struct thread *td; + int error; + int pathlen; UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n"); @@ -992,7 +993,7 @@ /* search vnode */ VOP_UNLOCK(ap->a_vp); error = unionfs_relookup(udvp, &vp, cnp, &cn, td, - cnp->cn_nameptr, strlen(cnp->cn_nameptr), DELETE); + cnp->cn_nameptr, cnp->cn_namelen, DELETE); if (error != 0 && error != ENOENT) { vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); return (error); @@ -1002,7 +1003,6 @@ /* target vnode in upper */ uvp = vp; vrele(vp); - path = NULL; } else { /* target vnode in lower */ if (vp != NULLVP) { @@ -1013,14 +1013,16 @@ } vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); lvp = ap->a_vp; - path = ap->a_cnp->cn_nameptr; } + path = cnp->cn_nameptr; + pathlen = cnp->cn_namelen; } else { ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount); unp = VTOUNIONFS(ap->a_vp); uvp = unp->un_uppervp; lvp = unp->un_lowervp; path = unp->un_path; + pathlen = unp->un_pathlen; } if (udvp == NULLVP) @@ -1036,7 +1038,7 @@ cnp->cn_flags |= DOWHITEOUT; error = VOP_REMOVE(udvp, uvp, cnp); } else if (lvp != NULLVP) - error = unionfs_mkwhiteout(udvp, cnp, td, path); + error = unionfs_mkwhiteout(udvp, cnp, td, path, pathlen); UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error); @@ -1262,7 +1264,7 @@ if (error != 0) goto unionfs_rename_abort; - /* Locke of tvp is canceled in order to avoid recursive lock. */ + /* Lock of tvp is canceled in order to avoid recursive lock. */ if (tvp != NULLVP && tvp != tdvp) VOP_UNLOCK(tvp); error = unionfs_relookup_for_rename(tdvp, tcnp, td); @@ -1421,7 +1423,8 @@ error = VOP_RMDIR(udvp, uvp, cnp); } else if (lvp != NULLVP) - error = unionfs_mkwhiteout(udvp, cnp, td, unp->un_path); + error = unionfs_mkwhiteout(udvp, cnp, td, + unp->un_path, unp->un_pathlen); if (error == 0) { cache_purge(ap->a_dvp);