diff options
| author | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
| commit | bb272221e9db79f13d454e1f3fb6b05013be985e (patch) | |
| tree | 36f4acc50e3fabac71fadd34c720c0a6011db470 /fs/xfs/libxfs/xfs_bmap.c | |
| parent | 253fd51e2f533552ae35a0c661705da6c4842c1b (diff) | |
| parent | 5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff) | |
Merge tag 'v4.13-rc1' into fixes
The fixes branch is based off a random pre-rc1 commit, because we had
some fixes that needed to go in before rc1 was released.
However we now need to fix some code that went in after that point, but
before rc1, so merge rc1 to get that code into fixes so we can fix it!
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 51 | 
1 files changed, 36 insertions, 15 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a7048eafa8e6..0a9880777c9c 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3992,7 +3992,7 @@ xfs_bmapi_read(  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&  	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { +	     mp, XFS_ERRTAG_BMAPIFORMAT))) {  		XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED;  	} @@ -4473,7 +4473,7 @@ xfs_bmapi_write(  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&  	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { +	     mp, XFS_ERRTAG_BMAPIFORMAT))) {  		XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED;  	} @@ -4694,7 +4694,7 @@ xfs_bmapi_remap(  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&  	     XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE), -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { +	     mp, XFS_ERRTAG_BMAPIFORMAT))) {  		XFS_ERROR_REPORT("xfs_bmapi_remap", XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED;  	} @@ -5434,6 +5434,7 @@ __xfs_bunmapi(  	int			whichfork;	/* data or attribute fork */  	xfs_fsblock_t		sum;  	xfs_filblks_t		len = *rlen;	/* length to unmap in file */ +	xfs_fileoff_t		max_len;  	trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); @@ -5455,6 +5456,16 @@ __xfs_bunmapi(  	ASSERT(len > 0);  	ASSERT(nexts >= 0); +	/* +	 * Guesstimate how many blocks we can unmap without running the risk of +	 * blowing out the transaction with a mix of EFIs and reflink +	 * adjustments. +	 */ +	if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) +		max_len = min(len, xfs_refcount_max_unmap(tp->t_log_res)); +	else +		max_len = len; +  	if (!(ifp->if_flags & XFS_IFEXTENTS) &&  	    (error = xfs_iread_extents(tp, ip, whichfork)))  		return error; @@ -5499,7 +5510,7 @@ __xfs_bunmapi(  	extno = 0;  	while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 && -	       (nexts == 0 || extno < nexts)) { +	       (nexts == 0 || extno < nexts) && max_len > 0) {  		/*  		 * Is the found extent after a hole in which bno lives?  		 * Just back up to the previous extent, if so. @@ -5531,6 +5542,15 @@ __xfs_bunmapi(  		}  		if (del.br_startoff + del.br_blockcount > bno + 1)  			del.br_blockcount = bno + 1 - del.br_startoff; + +		/* How much can we safely unmap? */ +		if (max_len < del.br_blockcount) { +			del.br_startoff += del.br_blockcount - max_len; +			if (!wasdel) +				del.br_startblock += del.br_blockcount - max_len; +			del.br_blockcount = max_len; +		} +  		sum = del.br_startblock + del.br_blockcount;  		if (isrt &&  		    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) { @@ -5707,6 +5727,7 @@ __xfs_bunmapi(  		if (!isrt && wasdel)  			xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount, false); +		max_len -= del.br_blockcount;  		bno = del.br_startoff - 1;  nodelete:  		/* @@ -6077,7 +6098,7 @@ xfs_bmap_shift_extents(  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&  	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { +	     mp, XFS_ERRTAG_BMAPIFORMAT))) {  		XFS_ERROR_REPORT("xfs_bmap_shift_extents",  				 XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED; @@ -6229,7 +6250,7 @@ xfs_bmap_split_extent_at(  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&  	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { +	     mp, XFS_ERRTAG_BMAPIFORMAT))) {  		XFS_ERROR_REPORT("xfs_bmap_split_extent_at",  				 XFS_ERRLEVEL_LOW, mp);  		return -EFSCORRUPTED; @@ -6472,33 +6493,33 @@ xfs_bmap_finish_one(  	int				whichfork,  	xfs_fileoff_t			startoff,  	xfs_fsblock_t			startblock, -	xfs_filblks_t			blockcount, +	xfs_filblks_t			*blockcount,  	xfs_exntst_t			state)  { -	int				error = 0, done; +	xfs_fsblock_t			firstfsb; +	int				error = 0;  	trace_xfs_bmap_deferred(tp->t_mountp,  			XFS_FSB_TO_AGNO(tp->t_mountp, startblock), type,  			XFS_FSB_TO_AGBNO(tp->t_mountp, startblock), -			ip->i_ino, whichfork, startoff, blockcount, state); +			ip->i_ino, whichfork, startoff, *blockcount, state);  	if (WARN_ON_ONCE(whichfork != XFS_DATA_FORK))  		return -EFSCORRUPTED;  	if (XFS_TEST_ERROR(false, tp->t_mountp, -			XFS_ERRTAG_BMAP_FINISH_ONE, -			XFS_RANDOM_BMAP_FINISH_ONE)) +			XFS_ERRTAG_BMAP_FINISH_ONE))  		return -EIO;  	switch (type) {  	case XFS_BMAP_MAP: -		error = xfs_bmapi_remap(tp, ip, startoff, blockcount, +		error = xfs_bmapi_remap(tp, ip, startoff, *blockcount,  				startblock, dfops); +		*blockcount = 0;  		break;  	case XFS_BMAP_UNMAP: -		error = xfs_bunmapi(tp, ip, startoff, blockcount, -				XFS_BMAPI_REMAP, 1, &startblock, dfops, &done); -		ASSERT(done); +		error = __xfs_bunmapi(tp, ip, startoff, blockcount, +				XFS_BMAPI_REMAP, 1, &firstfsb, dfops);  		break;  	default:  		ASSERT(0);  | 
