diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 17 | 
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 5b6092ef51ef..f0efc7e970ef 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents(  	int				whichfork = XFS_DATA_FORK;  	int				logflags;  	xfs_filblks_t			blockcount = 0; +	int				total_extents;  	if (unlikely(XFS_TEST_ERROR(  	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && @@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents(  	ASSERT(current_ext != NULL);  	ifp = XFS_IFORK_PTR(ip, whichfork); -  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {  		/* Read in all the extents */  		error = xfs_iread_extents(tp, ip, whichfork); @@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents(  	/* We are going to change core inode */  	logflags = XFS_ILOG_CORE; -  	if (ifp->if_flags & XFS_IFBROOT) {  		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);  		cur->bc_private.b.firstblock = *firstblock; @@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents(  		logflags |= XFS_ILOG_DEXT;  	} -	while (nexts++ < num_exts && -	       *current_ext <  XFS_IFORK_NEXTENTS(ip, whichfork)) { +	/* +	 * There may be delalloc extents in the data fork before the range we +	 * are collapsing out, so we cannot +	 * use the count of real extents here. Instead we have to calculate it +	 * from the incore fork. +	 */ +	total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); +	while (nexts++ < num_exts && *current_ext < total_extents) {  		gotp = xfs_iext_get_ext(ifp, *current_ext);  		xfs_bmbt_get_all(gotp, &got); @@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents(  		}  		(*current_ext)++; +		total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);  	}  	/* Check if we are done */ -	if (*current_ext ==  XFS_IFORK_NEXTENTS(ip, whichfork)) +	if (*current_ext == total_extents)  		*done = 1;  del_cursor: @@ -5568,6 +5574,5 @@ del_cursor:  			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);  	xfs_trans_log_inode(tp, ip, logflags); -  	return error;  }  | 
