FreeBSD/sys/fs/unionfs/union_subr.c
/*
 * Create a new vnode for create a new shadow file.
 * 
 * If an error is returned, *vpp will be invalid, otherwise it will hold a
 * locked, referenced and opened vnode.
 * 
 * unp is never updated.
 */
Create a new vnode for create a new shadow file.

If an error is returned, *vpp will be invalid, otherwise it will hold a
locked, referenced and opened vnode.

unp is never updated.
Create a new vnode for create a new shadow file . If an error is returned * vpp will be invalid otherwise it will hold a locked referenced and opened vnode . unp is never updated .
static int
unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
			   struct unionfs_node *unp, struct vattr *uvap,
			   struct thread *td)
{
	struct unionfs_mount *ump;
	struct vnode   *vp;
	struct vnode   *lvp;
	struct ucred   *cred;
	struct vattr	lva;
	int		fmode;
	int		error;
	struct componentname cn;
	ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount);
	vp = NULLVP;
	lvp = unp->un_lowervp;
	cred = td->td_ucred;
	fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL);
	error = 0;
	if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0)
		return (error);
	unionfs_create_uppervattr_core(ump, &lva, uvap, td);
	if (unp->un_path == NULL)
		panic("unionfs: un_path is null");
	cn.cn_namelen = strlen(unp->un_path);
	cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
	bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1);
	cn.cn_nameiop = CREATE;
	cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
	cn.cn_lkflags = LK_EXCLUSIVE;
	cn.cn_thread = td;
	cn.cn_cred = cred;
	cn.cn_nameptr = cn.cn_pnbuf;
	vref(udvp);
	if ((error = relookup(udvp, &vp, &cn)) != 0)
		goto unionfs_vn_create_on_upper_free_out2;
	vrele(udvp);
	if (vp != NULLVP) {
		if (vp == udvp)
			vrele(vp);
		else
			vput(vp);
		error = EEXIST;
		goto unionfs_vn_create_on_upper_free_out1;
	}
	if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0)
		goto unionfs_vn_create_on_upper_free_out1;
	if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) {
		vput(vp);
		goto unionfs_vn_create_on_upper_free_out1;
	}
	VOP_ADD_WRITECOUNT(vp, 1);
	CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",  __func__, vp,
	    vp->v_writecount);
	*vpp = vp;
unionfs_vn_create_on_upper_free_out1:
	VOP_UNLOCK(udvp, LK_RELEASE);
unionfs_vn_create_on_upper_free_out2:
	if (cn.cn_flags & HASBUF) {
		uma_zfree(namei_zone, cn.cn_pnbuf);
		cn.cn_flags &= ~HASBUF;
	}
	return (error);
}
static int unionfs_vn_create_on_upper ( struct vnode * * vpp , struct vnode * udvp , struct unionfs_node * unp , struct vattr * uvap , struct thread * td ) { struct unionfs_mount * ump ; struct vnode * vp ; struct vnode * lvp ; struct ucred * cred ; struct vattr lva ; int fmode ; int error ; struct componentname cn ; ump = MOUNTTOUNIONFSMOUNT ( UNIONFSTOV ( unp ) -> v_mount ) ; vp = NULLVP ; lvp = unp -> un_lowervp ; cred = td -> td_ucred ; fmode = FFLAGS ( O_WRONLY | O_CREAT | O_TRUNC | O_EXCL ) ; error = 0 ; if ( ( error = VOP_GETATTR ( lvp , & lva , cred ) ) != 0 ) return ( error ) ; unionfs_create_uppervattr_core ( ump , & lva , uvap , td ) ; if ( unp -> un_path == NULL ) panic ( " " ) ; cn . cn_namelen = strlen ( unp -> un_path ) ; cn . cn_pnbuf = uma_zalloc ( namei_zone , M_WAITOK ) ; bcopy ( unp -> un_path , cn . cn_pnbuf , cn . cn_namelen + 1 ) ; cn . cn_nameiop = CREATE ; cn . cn_flags = ( LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN ) ; cn . cn_lkflags = LK_EXCLUSIVE ; cn . cn_thread = td ; cn . cn_cred = cred ; cn . cn_nameptr = cn . cn_pnbuf ; vref ( udvp ) ; if ( ( error = relookup ( udvp , & vp , & cn ) ) != 0 ) goto unionfs_vn_create_on_upper_free_out2 ; vrele ( udvp ) ; if ( vp != NULLVP ) { if ( vp == udvp ) vrele ( vp ) ; else vput ( vp ) ; error = EEXIST ; goto unionfs_vn_create_on_upper_free_out1 ; } if ( ( error = VOP_CREATE ( udvp , & vp , & cn , uvap ) ) != 0 ) goto unionfs_vn_create_on_upper_free_out1 ; if ( ( error = VOP_OPEN ( vp , fmode , cred , td , NULL ) ) != 0 ) { vput ( vp ) ; goto unionfs_vn_create_on_upper_free_out1 ; } VOP_ADD_WRITECOUNT ( vp , 1 ) ; CTR3 ( KTR_VFS , " " , __func__ , vp , vp -> v_writecount ) ; * vpp = vp ; unionfs_vn_create_on_upper_free_out1 : VOP_UNLOCK ( udvp , LK_RELEASE ) ; unionfs_vn_create_on_upper_free_out2 : if ( cn . cn_flags & HASBUF ) { uma_zfree ( namei_zone , cn . cn_pnbuf ) ; cn . cn_flags &= ~ HASBUF ; } return ( error ) ; }
Create a new vnode for create a new shadow file.
Create a new vnode for create a new shadow file .