linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: darrick.wong@oracle.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 2/2] xfs: rewrite the COW writeback mapping code
Date: Sat, 24 Sep 2016 08:19:21 -0700	[thread overview]
Message-ID: <1474730361-5234-3-git-send-email-hch@lst.de> (raw)
In-Reply-To: <1474730361-5234-1-git-send-email-hch@lst.de>

Add a new xfs_map_cow helper that does a single consistent lookup in the
COW fork extent map, and remove the existing COW handling code from
xfs_map_blocks.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/xfs_aops.c | 119 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 69 insertions(+), 50 deletions(-)

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 1933803..2a3f4c1 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -357,15 +357,11 @@ xfs_map_blocks(
 	int			error = 0;
 	int			bmapi_flags = XFS_BMAPI_ENTIRE;
 	int			nimaps = 1;
-	int			whichfork;
-	bool			need_alloc;
 
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
-	whichfork = (type == XFS_IO_COW ? XFS_COW_FORK : XFS_DATA_FORK);
-	need_alloc = (type == XFS_IO_DELALLOC);
-
+	ASSERT(type != XFS_IO_COW);
 	if (type == XFS_IO_UNWRITTEN)
 		bmapi_flags |= XFS_BMAPI_IGSTATE;
 
@@ -378,36 +374,26 @@ xfs_map_blocks(
 		count = mp->m_super->s_maxbytes - offset;
 	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-
-	if (type == XFS_IO_COW) {
-		if (!xfs_reflink_find_cow_mapping(ip, offset, imap,
-						     &need_alloc)) {
-			WARN_ON_ONCE(1);
-			return -EIO;
-		}
-	} else {
-		error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
-				       imap, &nimaps, bmapi_flags);
-		/*
-		 * Truncate an overwrite extent if there's a pending CoW
-		 * reservation before the end of this extent.  This forces us
-		 * to come back to writepage to take care of the CoW.
-		 */
-		if (nimaps && type == XFS_IO_OVERWRITE)
-			xfs_reflink_trim_irec_to_next_cow(ip, offset_fsb, imap);
-	}
+	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
+				imap, &nimaps, bmapi_flags);
+	/*
+	 * Truncate an overwrite extent if there's a pending CoW
+	 * reservation before the end of this extent.  This forces us
+	 * to come back to writepage to take care of the CoW.
+	 */
+	if (nimaps && type == XFS_IO_OVERWRITE)
+		xfs_reflink_trim_irec_to_next_cow(ip, offset_fsb, imap);
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
 	if (error)
 		return error;
 
-	if (need_alloc &&
+	if (type == XFS_IO_DELALLOC &&
 	    (!nimaps || isnullstartblock(imap->br_startblock))) {
-		error = xfs_iomap_write_allocate(ip, whichfork, offset,
+		error = xfs_iomap_write_allocate(ip, XFS_DATA_FORK, offset,
 				imap);
 		if (!error)
-			trace_xfs_map_blocks_alloc(ip, offset, count, type,
-					imap);
+			trace_xfs_map_blocks_alloc(ip, offset, count, type, imap);
 		return error;
 	}
 
@@ -707,27 +693,6 @@ xfs_check_page_type(
 	return false;
 }
 
-/*
- * Figure out if CoW is pending at this offset.
- */
-static bool
-xfs_is_cow_io(
-	struct xfs_inode	*ip,
-	xfs_off_t		offset)
-{
-	struct xfs_bmbt_irec	imap;
-	bool			is_cow, need_alloc;
-
-	if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
-		return false;
-
-	xfs_ilock(ip, XFS_ILOCK_SHARED);
-	is_cow = xfs_reflink_find_cow_mapping(ip, offset, &imap, &need_alloc);
-	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
-	return is_cow;
-}
-
 STATIC void
 xfs_vm_invalidatepage(
 	struct page		*page,
@@ -804,6 +769,56 @@ out_invalidate:
 	return;
 }
 
+static int
+xfs_map_cow(
+	struct xfs_writepage_ctx *wpc,
+	struct inode		*inode,
+	loff_t			offset,
+	unsigned int		*new_type)
+{
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_bmbt_irec	imap;
+	bool			is_cow = false, need_alloc = false;
+	int			error;
+
+	/*
+	 * If we already have a valid COW mapping keep using it.
+	 */
+	if (wpc->io_type == XFS_IO_COW) {
+		wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap, offset);
+		if (wpc->imap_valid) {
+			*new_type = XFS_IO_COW;
+			return 0;
+		}
+	}
+
+	/*
+	 * Else we need to check if there is a COW mapping at this offset.
+	 */
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+	is_cow = xfs_reflink_find_cow_mapping(ip, offset, &imap, &need_alloc);
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+
+	if (!is_cow)
+		return 0;
+
+	/*
+	 * And if the COW mapping has a delayed extent here we need to
+	 * allocate real space for it now.
+	 */
+	if (need_alloc) {
+		error = xfs_iomap_write_allocate(ip, XFS_COW_FORK, offset,
+				&imap);
+		if (error)
+			return error;
+	}
+
+	wpc->io_type = *new_type = XFS_IO_COW;
+	wpc->imap_valid = true;
+	wpc->imap = imap;
+	return 0;
+}
+
 /*
  * We implement an immediate ioend submission policy here to avoid needing to
  * chain multiple ioends and hence nest mempool allocations which can violate
@@ -876,8 +891,12 @@ xfs_writepage_map(
 			continue;
 		}
 
-		if (xfs_is_cow_io(XFS_I(inode), offset))
-			new_type = XFS_IO_COW;
+		if (xfs_sb_version_hasreflink(&XFS_I(inode)->i_mount->m_sb)) {
+			error = xfs_map_cow(wpc, inode, offset, &new_type);
+			if (error)
+				goto out;
+		}
+
 		if (wpc->io_type != new_type) {
 			wpc->io_type = new_type;
 			wpc->imap_valid = false;
-- 
2.1.4


  parent reply	other threads:[~2016-09-24 15:19 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-24 15:19 only do a single COW fork lookup in writeback Christoph Hellwig
2016-09-24 15:19 ` [PATCH 1/2] xfs: kill xfs_reflink_is_cow_pending Christoph Hellwig
2016-09-26 21:08   ` Darrick J. Wong
2016-09-24 15:19 ` Christoph Hellwig [this message]
2016-09-26 21:35   ` [PATCH 2/2] xfs: rewrite the COW writeback mapping code Darrick J. Wong
2016-09-27 18:48     ` Christoph Hellwig
2016-09-25  3:47 ` only do a single COW fork lookup in writeback Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1474730361-5234-3-git-send-email-hch@lst.de \
    --to=hch@lst.de \
    --cc=darrick.wong@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).