Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/unionfs/union_subr.c
Show First 20 Lines • Show All 754 Lines • ▼ Show 20 Lines | unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp, | ||||
struct unionfs_node *unp, struct componentname *cnp, | struct unionfs_node *unp, struct componentname *cnp, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
int error; | int error; | ||||
struct vnode *lvp; | struct vnode *lvp; | ||||
struct vnode *uvp; | struct vnode *uvp; | ||||
struct vattr va; | struct vattr va; | ||||
struct vattr lva; | struct vattr lva; | ||||
struct componentname cn; | struct nameidata nd; | ||||
struct mount *mp; | struct mount *mp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
struct ucred *credbk; | struct ucred *credbk; | ||||
struct uidinfo *rootinfo; | struct uidinfo *rootinfo; | ||||
if (unp->un_uppervp != NULLVP) | if (unp->un_uppervp != NULLVP) | ||||
return (EEXIST); | return (EEXIST); | ||||
Show All 10 Lines | unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp, | ||||
*/ | */ | ||||
chgproccnt(cred->cr_ruidinfo, 1, 0); | chgproccnt(cred->cr_ruidinfo, 1, 0); | ||||
change_euid(cred, rootinfo); | change_euid(cred, rootinfo); | ||||
change_ruid(cred, rootinfo); | change_ruid(cred, rootinfo); | ||||
change_svuid(cred, (uid_t)0); | change_svuid(cred, (uid_t)0); | ||||
uifree(rootinfo); | uifree(rootinfo); | ||||
cnp->cn_cred = cred; | cnp->cn_cred = cred; | ||||
memset(&cn, 0, sizeof(cn)); | memset(&nd.ni_cnd, 0, sizeof(struct componentname)); | ||||
NDPREINIT(&nd); | |||||
if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) | if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred))) | ||||
goto unionfs_mkshadowdir_abort; | goto unionfs_mkshadowdir_abort; | ||||
if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, td, cnp->cn_nameptr, cnp->cn_namelen, CREATE))) | if ((error = unionfs_relookup(udvp, &uvp, cnp, &nd.ni_cnd, td, | ||||
cnp->cn_nameptr, cnp->cn_namelen, CREATE))) | |||||
goto unionfs_mkshadowdir_abort; | goto unionfs_mkshadowdir_abort; | ||||
if (uvp != NULLVP) { | if (uvp != NULLVP) { | ||||
if (udvp == uvp) | if (udvp == uvp) | ||||
vrele(uvp); | vrele(uvp); | ||||
else | else | ||||
vput(uvp); | vput(uvp); | ||||
error = EEXIST; | error = EEXIST; | ||||
goto unionfs_mkshadowdir_free_out; | goto unionfs_mkshadowdir_free_out; | ||||
} | } | ||||
if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH))) | if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH))) | ||||
goto unionfs_mkshadowdir_free_out; | goto unionfs_mkshadowdir_free_out; | ||||
unionfs_create_uppervattr_core(ump, &lva, &va, td); | unionfs_create_uppervattr_core(ump, &lva, &va, td); | ||||
error = VOP_MKDIR(udvp, &uvp, &cn, &va); | error = VOP_MKDIR(udvp, &uvp, &nd.ni_cnd, &va); | ||||
if (!error) { | if (!error) { | ||||
unionfs_node_update(unp, uvp, td); | unionfs_node_update(unp, uvp, td); | ||||
/* | /* | ||||
* XXX The bug which cannot set uid/gid was corrected. | * XXX The bug which cannot set uid/gid was corrected. | ||||
* Ignore errors. | * Ignore errors. | ||||
*/ | */ | ||||
va.va_type = VNON; | va.va_type = VNON; | ||||
VOP_SETATTR(uvp, &va, cn.cn_cred); | VOP_SETATTR(uvp, &va, nd.ni_cnd.cn_cred); | ||||
} | } | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
unionfs_mkshadowdir_free_out: | unionfs_mkshadowdir_free_out: | ||||
if (cn.cn_flags & HASBUF) { | if (nd.ni_cnd.cn_flags & HASBUF) { | ||||
uma_zfree(namei_zone, cn.cn_pnbuf); | uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); | ||||
cn.cn_flags &= ~HASBUF; | nd.ni_cnd.cn_flags &= ~HASBUF; | ||||
} | } | ||||
unionfs_mkshadowdir_abort: | unionfs_mkshadowdir_abort: | ||||
cnp->cn_cred = credbk; | cnp->cn_cred = credbk; | ||||
chgproccnt(cred->cr_ruidinfo, -1, 0); | chgproccnt(cred->cr_ruidinfo, -1, 0); | ||||
crfree(cred); | crfree(cred); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Create a new whiteout. | * Create a new whiteout. | ||||
* | * | ||||
* dvp should be locked on entry and will be locked on return. | * dvp should be locked on entry and will be locked on return. | ||||
*/ | */ | ||||
int | int | ||||
unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, | unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp, | ||||
struct thread *td, char *path) | struct thread *td, char *path) | ||||
{ | { | ||||
int error; | int error; | ||||
struct vnode *wvp; | struct vnode *wvp; | ||||
struct componentname cn; | struct nameidata nd; | ||||
struct mount *mp; | struct mount *mp; | ||||
if (path == NULL) | if (path == NULL) | ||||
path = cnp->cn_nameptr; | path = cnp->cn_nameptr; | ||||
wvp = NULLVP; | wvp = NULLVP; | ||||
if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, td, path, strlen(path), CREATE))) | NDPREINIT(&nd); | ||||
if ((error = unionfs_relookup(dvp, &wvp, cnp, &nd.ni_cnd, td, path, | |||||
strlen(path), CREATE))) | |||||
return (error); | return (error); | ||||
if (wvp != NULLVP) { | if (wvp != NULLVP) { | ||||
if (cn.cn_flags & HASBUF) { | if (nd.ni_cnd.cn_flags & HASBUF) { | ||||
uma_zfree(namei_zone, cn.cn_pnbuf); | uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); | ||||
cn.cn_flags &= ~HASBUF; | nd.ni_cnd.cn_flags &= ~HASBUF; | ||||
} | } | ||||
if (dvp == wvp) | if (dvp == wvp) | ||||
vrele(wvp); | vrele(wvp); | ||||
else | else | ||||
vput(wvp); | vput(wvp); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH))) | if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH))) | ||||
goto unionfs_mkwhiteout_free_out; | goto unionfs_mkwhiteout_free_out; | ||||
error = VOP_WHITEOUT(dvp, &cn, CREATE); | error = VOP_WHITEOUT(dvp, &nd.ni_cnd, CREATE); | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
unionfs_mkwhiteout_free_out: | unionfs_mkwhiteout_free_out: | ||||
if (cn.cn_flags & HASBUF) { | if (nd.ni_cnd.cn_flags & HASBUF) { | ||||
uma_zfree(namei_zone, cn.cn_pnbuf); | uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); | ||||
cn.cn_flags &= ~HASBUF; | nd.ni_cnd.cn_flags &= ~HASBUF; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Create a new vnode for create a new shadow file. | * Create a new vnode for create a new shadow file. | ||||
* | * | ||||
Show All 9 Lines | |||||
{ | { | ||||
struct unionfs_mount *ump; | struct unionfs_mount *ump; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct vnode *lvp; | struct vnode *lvp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
struct vattr lva; | struct vattr lva; | ||||
int fmode; | int fmode; | ||||
int error; | int error; | ||||
struct componentname cn; | struct nameidata nd; | ||||
ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); | ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount); | ||||
vp = NULLVP; | vp = NULLVP; | ||||
lvp = unp->un_lowervp; | lvp = unp->un_lowervp; | ||||
cred = td->td_ucred; | cred = td->td_ucred; | ||||
fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); | fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL); | ||||
error = 0; | error = 0; | ||||
if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0) | if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0) | ||||
return (error); | return (error); | ||||
unionfs_create_uppervattr_core(ump, &lva, uvap, td); | unionfs_create_uppervattr_core(ump, &lva, uvap, td); | ||||
if (unp->un_path == NULL) | if (unp->un_path == NULL) | ||||
panic("unionfs: un_path is null"); | panic("unionfs: un_path is null"); | ||||
cn.cn_namelen = strlen(unp->un_path); | nd.ni_cnd.cn_namelen = strlen(unp->un_path); | ||||
cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); | nd.ni_cnd.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); | ||||
bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1); | bcopy(unp->un_path, nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_namelen + 1); | ||||
cn.cn_nameiop = CREATE; | nd.ni_cnd.cn_nameiop = CREATE; | ||||
cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN); | nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | | ||||
cn.cn_lkflags = LK_EXCLUSIVE; | ISLASTCN; | ||||
cn.cn_thread = td; | nd.ni_cnd.cn_lkflags = LK_EXCLUSIVE; | ||||
cn.cn_cred = cred; | nd.ni_cnd.cn_thread = td; | ||||
cn.cn_nameptr = cn.cn_pnbuf; | nd.ni_cnd.cn_cred = cred; | ||||
nd.ni_cnd.cn_nameptr = nd.ni_cnd.cn_pnbuf; | |||||
NDPREINIT(&nd); | |||||
vref(udvp); | vref(udvp); | ||||
if ((error = relookup(udvp, &vp, &cn)) != 0) | if ((error = relookup(udvp, &vp, &nd.ni_cnd)) != 0) | ||||
goto unionfs_vn_create_on_upper_free_out2; | goto unionfs_vn_create_on_upper_free_out2; | ||||
vrele(udvp); | vrele(udvp); | ||||
if (vp != NULLVP) { | if (vp != NULLVP) { | ||||
if (vp == udvp) | if (vp == udvp) | ||||
vrele(vp); | vrele(vp); | ||||
else | else | ||||
vput(vp); | vput(vp); | ||||
error = EEXIST; | error = EEXIST; | ||||
goto unionfs_vn_create_on_upper_free_out1; | goto unionfs_vn_create_on_upper_free_out1; | ||||
} | } | ||||
if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0) | if ((error = VOP_CREATE(udvp, &vp, &nd.ni_cnd, uvap)) != 0) | ||||
goto unionfs_vn_create_on_upper_free_out1; | goto unionfs_vn_create_on_upper_free_out1; | ||||
if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) { | if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) { | ||||
vput(vp); | vput(vp); | ||||
goto unionfs_vn_create_on_upper_free_out1; | goto unionfs_vn_create_on_upper_free_out1; | ||||
} | } | ||||
error = VOP_ADD_WRITECOUNT(vp, 1); | error = VOP_ADD_WRITECOUNT(vp, 1); | ||||
CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d", __func__, vp, | CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d", __func__, vp, | ||||
vp->v_writecount); | vp->v_writecount); | ||||
if (error == 0) { | if (error == 0) { | ||||
*vpp = vp; | *vpp = vp; | ||||
} else { | } else { | ||||
VOP_CLOSE(vp, fmode, cred, td); | VOP_CLOSE(vp, fmode, cred, td); | ||||
} | } | ||||
unionfs_vn_create_on_upper_free_out1: | unionfs_vn_create_on_upper_free_out1: | ||||
VOP_UNLOCK(udvp); | VOP_UNLOCK(udvp); | ||||
unionfs_vn_create_on_upper_free_out2: | unionfs_vn_create_on_upper_free_out2: | ||||
if (cn.cn_flags & HASBUF) { | if (nd.ni_cnd.cn_flags & HASBUF) { | ||||
uma_zfree(namei_zone, cn.cn_pnbuf); | uma_zfree(namei_zone, nd.ni_cnd.cn_pnbuf); | ||||
cn.cn_flags &= ~HASBUF; | nd.ni_cnd.cn_flags &= ~HASBUF; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Copy from lvp to uvp. | * Copy from lvp to uvp. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 304 Lines • Show Last 20 Lines |