diff options
| author | Sage Weil <sage@inktank.com> | 2013-08-15 11:11:45 -0700 | 
|---|---|---|
| committer | Sage Weil <sage@inktank.com> | 2013-08-15 11:11:45 -0700 | 
| commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
| tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/xfs/xfs_symlink.c | |
| parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
| parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) | |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/xfs/xfs_symlink.c')
| -rw-r--r-- | fs/xfs/xfs_symlink.c | 61 | 
1 files changed, 55 insertions, 6 deletions
| diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 195a403e1522..f4895b662fcb 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -358,7 +358,9 @@ xfs_symlink(  	int			n;  	xfs_buf_t		*bp;  	prid_t			prid; -	struct xfs_dquot	*udqp, *gdqp; +	struct xfs_dquot	*udqp = NULL; +	struct xfs_dquot	*gdqp = NULL; +	struct xfs_dquot	*pdqp = NULL;  	uint			resblks;  	*ipp = NULL; @@ -385,7 +387,7 @@ xfs_symlink(  	 * Make sure that we have allocated dquot(s) on disk.  	 */  	error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, -			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); +		XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp);  	if (error)  		goto std_return; @@ -426,7 +428,8 @@ xfs_symlink(  	/*  	 * Reserve disk quota : blocks and inode.  	 */ -	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); +	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, +						pdqp, resblks, 1, 0);  	if (error)  		goto error_return; @@ -464,7 +467,7 @@ xfs_symlink(  	/*  	 * Also attach the dquot(s) to it, if applicable.  	 */ -	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); +	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);  	if (resblks)  		resblks -= XFS_IALLOC_SPACE_RES(mp); @@ -562,6 +565,7 @@ xfs_symlink(  	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);  	xfs_qm_dqrele(udqp);  	xfs_qm_dqrele(gdqp); +	xfs_qm_dqrele(pdqp);  	*ipp = ip;  	return 0; @@ -575,6 +579,7 @@ xfs_symlink(  	xfs_trans_cancel(tp, cancel_flags);  	xfs_qm_dqrele(udqp);  	xfs_qm_dqrele(gdqp); +	xfs_qm_dqrele(pdqp);  	if (unlock_dp_on_error)  		xfs_iunlock(dp, XFS_ILOCK_EXCL); @@ -585,7 +590,7 @@ xfs_symlink(  /*   * Free a symlink that has blocks associated with it.   */ -int +STATIC int  xfs_inactive_symlink_rmt(  	xfs_inode_t	*ip,  	xfs_trans_t	**tpp) @@ -606,7 +611,7 @@ xfs_inactive_symlink_rmt(  	tp = *tpp;  	mp = ip->i_mount; -	ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip)); +	ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS);  	/*  	 * We're freeing a symlink that has some  	 * blocks allocated to it.  Free the @@ -720,3 +725,47 @@ xfs_inactive_symlink_rmt(   error0:  	return error;  } + +/* + * xfs_inactive_symlink - free a symlink + */ +int +xfs_inactive_symlink( +	struct xfs_inode	*ip, +	struct xfs_trans	**tp) +{ +	struct xfs_mount	*mp = ip->i_mount; +	int			pathlen; + +	trace_xfs_inactive_symlink(ip); + +	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + +	if (XFS_FORCED_SHUTDOWN(mp)) +		return XFS_ERROR(EIO); + +	/* +	 * Zero length symlinks _can_ exist. +	 */ +	pathlen = (int)ip->i_d.di_size; +	if (!pathlen) +		return 0; + +	if (pathlen < 0 || pathlen > MAXPATHLEN) { +		xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", +			 __func__, (unsigned long long)ip->i_ino, pathlen); +		ASSERT(0); +		return XFS_ERROR(EFSCORRUPTED); +	} + +	if (ip->i_df.if_flags & XFS_IFINLINE) { +		if (ip->i_df.if_bytes > 0) +			xfs_idata_realloc(ip, -(ip->i_df.if_bytes), +					  XFS_DATA_FORK); +		ASSERT(ip->i_df.if_bytes == 0); +		return 0; +	} + +	/* remove the remote symlink */ +	return xfs_inactive_symlink_rmt(ip, tp); +} | 
