diff options
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
| -rw-r--r-- | fs/xfs/xfs_reflink.c | 18 | 
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index ecdb086bc23e..322a852ce284 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -296,6 +296,7 @@ xfs_reflink_reserve_cow(  	if (error)  		return error; +	xfs_trim_extent(imap, got.br_startoff, got.br_blockcount);  	trace_xfs_reflink_cow_alloc(ip, &got);  	return 0;  } @@ -1351,10 +1352,19 @@ xfs_reflink_remap_prep(  	if (ret)  		goto out_unlock; -	/* Zap any page cache for the destination file's range. */ -	truncate_inode_pages_range(&inode_out->i_data, -			round_down(pos_out, PAGE_SIZE), -			round_up(pos_out + *len, PAGE_SIZE) - 1); +	/* +	 * If pos_out > EOF, we may have dirtied blocks between EOF and +	 * pos_out. In that case, we need to extend the flush and unmap to cover +	 * from EOF to the end of the copy length. +	 */ +	if (pos_out > XFS_ISIZE(dest)) { +		loff_t	flen = *len + (pos_out - XFS_ISIZE(dest)); +		ret = xfs_flush_unmap_range(dest, XFS_ISIZE(dest), flen); +	} else { +		ret = xfs_flush_unmap_range(dest, pos_out, *len); +	} +	if (ret) +		goto out_unlock;  	return 1;  out_unlock:  | 
