diff mbox series

[18/19] xfs: cleanup xfs_iomap_write_unwritten

Message ID 20190909182722.16783-19-hch@lst.de (mailing list archive)
State Superseded
Headers show
Series [01/19] iomap: better document the IOMAP_F_* flags | expand

Commit Message

Christoph Hellwig Sept. 9, 2019, 6:27 p.m. UTC
Move more checks into the helpers that determine if we need a COW
operation or allocation and split the return path for when an existing
data for allocation has been found versus a new allocation.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_iomap.c | 74 ++++++++++++++++++++++++----------------------
 1 file changed, 38 insertions(+), 36 deletions(-)

Comments

Darrick J. Wong Sept. 18, 2019, 6:06 p.m. UTC | #1
On Mon, Sep 09, 2019 at 08:27:21PM +0200, Christoph Hellwig wrote:
> Move more checks into the helpers that determine if we need a COW
> operation or allocation and split the return path for when an existing
> data for allocation has been found versus a new allocation.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Looks ok,
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/xfs/xfs_iomap.c | 74 ++++++++++++++++++++++++----------------------
>  1 file changed, 38 insertions(+), 36 deletions(-)
> 
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 0e575ca1e3fc..e4e79aa5b695 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -642,23 +642,42 @@ xfs_iomap_write_unwritten(
>  static inline bool
>  imap_needs_alloc(
>  	struct inode		*inode,
> +	unsigned		flags,
>  	struct xfs_bmbt_irec	*imap,
>  	int			nimaps)
>  {
> -	return !nimaps ||
> -		imap->br_startblock == HOLESTARTBLOCK ||
> -		imap->br_startblock == DELAYSTARTBLOCK ||
> -		(IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN);
> +	/* don't allocate blocks when just zeroing */
> +	if (flags & IOMAP_ZERO)
> +		return false;
> +	if (!nimaps ||
> +	    imap->br_startblock == HOLESTARTBLOCK ||
> +	    imap->br_startblock == DELAYSTARTBLOCK)
> +		return true;
> +	/* we convert unwritten extents before copying the data for DAX */
> +	if (IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN)
> +		return true;
> +	return false;
>  }
>  
>  static inline bool
> -needs_cow_for_zeroing(
> +imap_needs_cow(
> +	struct xfs_inode	*ip,
>  	struct xfs_bmbt_irec	*imap,
> +	unsigned int		flags,
>  	int			nimaps)
>  {
> -	return nimaps &&
> -		imap->br_startblock != HOLESTARTBLOCK &&
> -		imap->br_state != XFS_EXT_UNWRITTEN;
> +	if (!xfs_is_cow_inode(ip))
> +		return false;
> +
> +	/* when zeroing we don't have to COW holes or unwritten extents */
> +	if (flags & IOMAP_ZERO) {
> +		if (!nimaps ||
> +		    imap->br_startblock == HOLESTARTBLOCK ||
> +		    imap->br_state == XFS_EXT_UNWRITTEN)
> +			return false;
> +	}
> +
> +	return true;
>  }
>  
>  static int
> @@ -734,7 +753,6 @@ xfs_direct_write_iomap_begin(
>  	xfs_fileoff_t		end_fsb = xfs_iomap_end_fsb(mp, offset, length);
>  	int			nimaps = 1, error = 0;
>  	bool			shared = false;
> -	u16			iomap_flags = 0;
>  	unsigned		lockmode;
>  
>  	ASSERT(flags & (IOMAP_WRITE | IOMAP_ZERO));
> @@ -761,12 +779,7 @@ xfs_direct_write_iomap_begin(
>  	 * Break shared extents if necessary. Checks for non-blocking IO have
>  	 * been done up front, so we don't need to do them here.
>  	 */
> -	if (xfs_is_cow_inode(ip)) {
> -		/* if zeroing doesn't need COW allocation, then we are done. */
> -		if ((flags & IOMAP_ZERO) &&
> -		    !needs_cow_for_zeroing(&imap, nimaps))
> -			goto out_found;
> -
> +	if (imap_needs_cow(ip, &imap, flags, nimaps)) {
>  		/* may drop and re-acquire the ilock */
>  		error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
>  				&lockmode, flags & IOMAP_DIRECT);
> @@ -778,18 +791,17 @@ xfs_direct_write_iomap_begin(
>  		length = XFS_FSB_TO_B(mp, end_fsb) - offset;
>  	}
>  
> -	/* Don't need to allocate over holes when doing zeroing operations. */
> -	if (flags & IOMAP_ZERO)
> -		goto out_found;
> +	if (imap_needs_alloc(inode, flags, &imap, nimaps))
> +		goto allocate_blocks;
>  
> -	if (!imap_needs_alloc(inode, &imap, nimaps))
> -		goto out_found;
> +	xfs_iunlock(ip, lockmode);
> +	trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
> +	return xfs_bmbt_to_iomap(ip, iomap, &imap, 0);
>  
> -	/* If nowait is set bail since we are going to make allocations. */
> -	if (flags & IOMAP_NOWAIT) {
> -		error = -EAGAIN;
> +allocate_blocks:
> +	error = -EAGAIN;
> +	if (flags & IOMAP_NOWAIT)
>  		goto out_unlock;
> -	}
>  
>  	/*
>  	 * We cap the maximum length we map to a sane size  to keep the chunks
> @@ -808,22 +820,12 @@ xfs_direct_write_iomap_begin(
>  	 */
>  	if (lockmode == XFS_ILOCK_EXCL)
>  		xfs_ilock_demote(ip, lockmode);
> -	error = xfs_iomap_write_direct(ip, offset, length, &imap,
> -			nimaps);
> +	error = xfs_iomap_write_direct(ip, offset, length, &imap, nimaps);
>  	if (error)
>  		return error;
>  
> -	iomap_flags |= IOMAP_F_NEW;
>  	trace_xfs_iomap_alloc(ip, offset, length, XFS_DATA_FORK, &imap);
> -
> -out_finish:
> -	return xfs_bmbt_to_iomap(ip, iomap, &imap, iomap_flags);
> -
> -out_found:
> -	ASSERT(nimaps);
> -	xfs_iunlock(ip, lockmode);
> -	trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
> -	goto out_finish;
> +	return xfs_bmbt_to_iomap(ip, iomap, &imap, IOMAP_F_NEW);
>  
>  out_found_cow:
>  	xfs_iunlock(ip, lockmode);
> -- 
> 2.20.1
>
diff mbox series

Patch

diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 0e575ca1e3fc..e4e79aa5b695 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -642,23 +642,42 @@  xfs_iomap_write_unwritten(
 static inline bool
 imap_needs_alloc(
 	struct inode		*inode,
+	unsigned		flags,
 	struct xfs_bmbt_irec	*imap,
 	int			nimaps)
 {
-	return !nimaps ||
-		imap->br_startblock == HOLESTARTBLOCK ||
-		imap->br_startblock == DELAYSTARTBLOCK ||
-		(IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN);
+	/* don't allocate blocks when just zeroing */
+	if (flags & IOMAP_ZERO)
+		return false;
+	if (!nimaps ||
+	    imap->br_startblock == HOLESTARTBLOCK ||
+	    imap->br_startblock == DELAYSTARTBLOCK)
+		return true;
+	/* we convert unwritten extents before copying the data for DAX */
+	if (IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN)
+		return true;
+	return false;
 }
 
 static inline bool
-needs_cow_for_zeroing(
+imap_needs_cow(
+	struct xfs_inode	*ip,
 	struct xfs_bmbt_irec	*imap,
+	unsigned int		flags,
 	int			nimaps)
 {
-	return nimaps &&
-		imap->br_startblock != HOLESTARTBLOCK &&
-		imap->br_state != XFS_EXT_UNWRITTEN;
+	if (!xfs_is_cow_inode(ip))
+		return false;
+
+	/* when zeroing we don't have to COW holes or unwritten extents */
+	if (flags & IOMAP_ZERO) {
+		if (!nimaps ||
+		    imap->br_startblock == HOLESTARTBLOCK ||
+		    imap->br_state == XFS_EXT_UNWRITTEN)
+			return false;
+	}
+
+	return true;
 }
 
 static int
@@ -734,7 +753,6 @@  xfs_direct_write_iomap_begin(
 	xfs_fileoff_t		end_fsb = xfs_iomap_end_fsb(mp, offset, length);
 	int			nimaps = 1, error = 0;
 	bool			shared = false;
-	u16			iomap_flags = 0;
 	unsigned		lockmode;
 
 	ASSERT(flags & (IOMAP_WRITE | IOMAP_ZERO));
@@ -761,12 +779,7 @@  xfs_direct_write_iomap_begin(
 	 * Break shared extents if necessary. Checks for non-blocking IO have
 	 * been done up front, so we don't need to do them here.
 	 */
-	if (xfs_is_cow_inode(ip)) {
-		/* if zeroing doesn't need COW allocation, then we are done. */
-		if ((flags & IOMAP_ZERO) &&
-		    !needs_cow_for_zeroing(&imap, nimaps))
-			goto out_found;
-
+	if (imap_needs_cow(ip, &imap, flags, nimaps)) {
 		/* may drop and re-acquire the ilock */
 		error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
 				&lockmode, flags & IOMAP_DIRECT);
@@ -778,18 +791,17 @@  xfs_direct_write_iomap_begin(
 		length = XFS_FSB_TO_B(mp, end_fsb) - offset;
 	}
 
-	/* Don't need to allocate over holes when doing zeroing operations. */
-	if (flags & IOMAP_ZERO)
-		goto out_found;
+	if (imap_needs_alloc(inode, flags, &imap, nimaps))
+		goto allocate_blocks;
 
-	if (!imap_needs_alloc(inode, &imap, nimaps))
-		goto out_found;
+	xfs_iunlock(ip, lockmode);
+	trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
+	return xfs_bmbt_to_iomap(ip, iomap, &imap, 0);
 
-	/* If nowait is set bail since we are going to make allocations. */
-	if (flags & IOMAP_NOWAIT) {
-		error = -EAGAIN;
+allocate_blocks:
+	error = -EAGAIN;
+	if (flags & IOMAP_NOWAIT)
 		goto out_unlock;
-	}
 
 	/*
 	 * We cap the maximum length we map to a sane size  to keep the chunks
@@ -808,22 +820,12 @@  xfs_direct_write_iomap_begin(
 	 */
 	if (lockmode == XFS_ILOCK_EXCL)
 		xfs_ilock_demote(ip, lockmode);
-	error = xfs_iomap_write_direct(ip, offset, length, &imap,
-			nimaps);
+	error = xfs_iomap_write_direct(ip, offset, length, &imap, nimaps);
 	if (error)
 		return error;
 
-	iomap_flags |= IOMAP_F_NEW;
 	trace_xfs_iomap_alloc(ip, offset, length, XFS_DATA_FORK, &imap);
-
-out_finish:
-	return xfs_bmbt_to_iomap(ip, iomap, &imap, iomap_flags);
-
-out_found:
-	ASSERT(nimaps);
-	xfs_iunlock(ip, lockmode);
-	trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
-	goto out_finish;
+	return xfs_bmbt_to_iomap(ip, iomap, &imap, IOMAP_F_NEW);
 
 out_found_cow:
 	xfs_iunlock(ip, lockmode);