diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 25 | 
1 files changed, 18 insertions, 7 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 41662fb14e87..288ee5b840d7 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -630,6 +630,11 @@ retry:  		goto out_unlock;  	} +	/* +	 * Flag newly allocated delalloc blocks with IOMAP_F_NEW so we punch +	 * them out if the write happens to fail. +	 */ +	iomap->flags = IOMAP_F_NEW;  	trace_xfs_iomap_alloc(ip, offset, count, 0, &got);  done:  	if (isnullstartblock(got.br_startblock)) @@ -1071,16 +1076,22 @@ xfs_file_iomap_end_delalloc(  	struct xfs_inode	*ip,  	loff_t			offset,  	loff_t			length, -	ssize_t			written) +	ssize_t			written, +	struct iomap		*iomap)  {  	struct xfs_mount	*mp = ip->i_mount;  	xfs_fileoff_t		start_fsb;  	xfs_fileoff_t		end_fsb;  	int			error = 0; -	/* behave as if the write failed if drop writes is enabled */ -	if (xfs_mp_drop_writes(mp)) +	/* +	 * Behave as if the write failed if drop writes is enabled. Set the NEW +	 * flag to force delalloc cleanup. +	 */ +	if (xfs_mp_drop_writes(mp)) { +		iomap->flags |= IOMAP_F_NEW;  		written = 0; +	}  	/*  	 * start_fsb refers to the first unused block after a short write. If @@ -1094,14 +1105,14 @@ xfs_file_iomap_end_delalloc(  	end_fsb = XFS_B_TO_FSB(mp, offset + length);  	/* -	 * Trim back delalloc blocks if we didn't manage to write the whole -	 * range reserved. +	 * Trim delalloc blocks if they were allocated by this write and we +	 * didn't manage to write the whole range.  	 *  	 * We don't need to care about racing delalloc as we hold i_mutex  	 * across the reserve/allocate/unreserve calls. If there are delalloc  	 * blocks in the range, they are ours.  	 */ -	if (start_fsb < end_fsb) { +	if ((iomap->flags & IOMAP_F_NEW) && start_fsb < end_fsb) {  		truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),  					 XFS_FSB_TO_B(mp, end_fsb) - 1); @@ -1131,7 +1142,7 @@ xfs_file_iomap_end(  {  	if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC)  		return xfs_file_iomap_end_delalloc(XFS_I(inode), offset, -				length, written); +				length, written, iomap);  	return 0;  }  | 

