diff options
Diffstat (limited to 'fs/xfs/xfs_rtalloc.c')
| -rw-r--r-- | fs/xfs/xfs_rtalloc.c | 49 | 
1 files changed, 37 insertions, 12 deletions
| diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 4e7be6b4ca8e..699066fb9052 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -923,16 +923,41 @@ xfs_growfs_rt(  	uint8_t		*rsum_cache;	/* old summary cache */  	sbp = &mp->m_sb; -	/* -	 * Initial error checking. -	 */ +  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL || -	    (nrblocks = in->newblocks) <= sbp->sb_rblocks || -	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize))) + +	/* Needs to have been mounted with an rt device. */ +	if (!XFS_IS_REALTIME_MOUNT(mp)) +		return -EINVAL; +	/* +	 * Mount should fail if the rt bitmap/summary files don't load, but +	 * we'll check anyway. +	 */ +	if (!mp->m_rbmip || !mp->m_rsumip) +		return -EINVAL; + +	/* Shrink not supported. */ +	if (in->newblocks <= sbp->sb_rblocks) +		return -EINVAL; + +	/* Can only change rt extent size when adding rt volume. */ +	if (sbp->sb_rblocks > 0 && in->extsize != sbp->sb_rextsize) +		return -EINVAL; + +	/* Range check the extent size. */ +	if (XFS_FSB_TO_B(mp, in->extsize) > XFS_MAX_RTEXTSIZE || +	    XFS_FSB_TO_B(mp, in->extsize) < XFS_MIN_RTEXTSIZE)  		return -EINVAL; -	if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks))) + +	/* Unsupported realtime features. */ +	if (xfs_sb_version_hasrmapbt(&mp->m_sb) || +	    xfs_sb_version_hasreflink(&mp->m_sb)) +		return -EOPNOTSUPP; + +	nrblocks = in->newblocks; +	error = xfs_sb_validate_fsb_count(sbp, nrblocks); +	if (error)  		return error;  	/*  	 * Read in the last block of the device, make sure it exists. @@ -996,7 +1021,8 @@ xfs_growfs_rt(  		     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);  	     bmbno < nrbmblocks;  	     bmbno++) { -		xfs_trans_t	*tp; +		struct xfs_trans	*tp; +		xfs_rfsblock_t		nrblocks_step;  		*nmp = *mp;  		nsbp = &nmp->m_sb; @@ -1005,10 +1031,9 @@ xfs_growfs_rt(  		 */  		nsbp->sb_rextsize = in->extsize;  		nsbp->sb_rbmblocks = bmbno + 1; -		nsbp->sb_rblocks = -			XFS_RTMIN(nrblocks, -				  nsbp->sb_rbmblocks * NBBY * -				  nsbp->sb_blocksize * nsbp->sb_rextsize); +		nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize * +				nsbp->sb_rextsize; +		nsbp->sb_rblocks = min(nrblocks, nrblocks_step);  		nsbp->sb_rextents = nsbp->sb_rblocks;  		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);  		ASSERT(nsbp->sb_rextents != 0); |