[PATCH 1/2] xfs: kill xfs_reflink_is_cow_pending

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead enhance xfs_reflink_find_cow_mapping to properly deal with the
fact that we might not have a COW mapping at the offset, and just
return false in this case.

This avoids code duplication, makes xfs_reflink_find_cow_mapping more
robust, and last but not least halves the number of extent map lookups
needed in COW writeback operations.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>
---
 fs/xfs/xfs_aops.c    | 28 ++++++++++++++++------------
 fs/xfs/xfs_reflink.c | 42 +++++++++++-------------------------------
 fs/xfs/xfs_reflink.h |  3 +--
 3 files changed, 28 insertions(+), 45 deletions(-)

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index d8ce18b..1933803 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -379,10 +379,13 @@ xfs_map_blocks(
 	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)
-		error = xfs_reflink_find_cow_mapping(ip, offset, imap,
-						     &need_alloc);
-	else {
+	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);
 		/*
@@ -712,13 +715,14 @@ xfs_is_cow_io(
 	struct xfs_inode	*ip,
 	xfs_off_t		offset)
 {
-	bool			is_cow;
+	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_is_cow_pending(ip, offset);
+	is_cow = xfs_reflink_find_cow_mapping(ip, offset, &imap, &need_alloc);
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
 	return is_cow;
@@ -1316,12 +1320,12 @@ __xfs_get_blocks(
 	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
-	if (create && direct)
-		is_cow = xfs_reflink_is_cow_pending(ip, offset);
-	if (is_cow)
-		error = xfs_reflink_find_cow_mapping(ip, offset, &imap,
-						     &need_alloc);
-	else {
+	if (create && direct) {
+		is_cow = xfs_reflink_find_cow_mapping(ip, offset, &imap,
+					&need_alloc);
+	}
+
+	if (!is_cow) {
 		error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
 					&imap, &nimaps, XFS_BMAPI_ENTIRE);
 		/*
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 6f87b1e..a1ba7f5 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -429,26 +429,31 @@ advloop:
 }
 
 /*
- * Determine if there's a CoW reservation at a byte offset of an inode.
+ * Find the CoW reservation (and whether or not it needs block allocation)
+ * for a given byte offset of a file.
  */
 bool
-xfs_reflink_is_cow_pending(
+xfs_reflink_find_cow_mapping(
 	struct xfs_inode		*ip,
-	xfs_off_t			offset)
+	xfs_off_t			offset,
+	struct xfs_bmbt_irec		*imap,
+	bool				*need_alloc)
 {
+	struct xfs_bmbt_irec		irec;
 	struct xfs_ifork		*ifp;
 	struct xfs_bmbt_rec_host	*gotp;
-	struct xfs_bmbt_irec		irec;
 	xfs_fileoff_t			bno;
 	xfs_extnum_t			idx;
 
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
+
 	if (!xfs_is_reflink_inode(ip))
 		return false;
 
+	/* Find the extent in the CoW fork. */
 	ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
 	bno = XFS_B_TO_FSBT(ip->i_mount, offset);
 	gotp = xfs_iext_bno_to_ext(ifp, bno, &idx);
-
 	if (!gotp)
 		return false;
 
@@ -456,31 +461,6 @@ xfs_reflink_is_cow_pending(
 	if (bno >= irec.br_startoff + irec.br_blockcount ||
 	    bno < irec.br_startoff)
 		return false;
-	return true;
-}
-
-/*
- * Find the CoW reservation (and whether or not it needs block allocation)
- * for a given byte offset of a file.
- */
-int
-xfs_reflink_find_cow_mapping(
-	struct xfs_inode		*ip,
-	xfs_off_t			offset,
-	struct xfs_bmbt_irec		*imap,
-	bool				*need_alloc)
-{
-	struct xfs_bmbt_irec		irec;
-	struct xfs_ifork		*ifp;
-	struct xfs_bmbt_rec_host	*gotp;
-	xfs_fileoff_t			bno;
-	xfs_extnum_t			idx;
-
-	/* Find the extent in the CoW fork. */
-	ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
-	bno = XFS_B_TO_FSBT(ip->i_mount, offset);
-	gotp = xfs_iext_bno_to_ext(ifp, bno, &idx);
-	xfs_bmbt_get_all(gotp, &irec);
 
 	trace_xfs_reflink_find_cow_mapping(ip, offset, 1, XFS_IO_OVERWRITE,
 			&irec);
@@ -489,7 +469,7 @@ xfs_reflink_find_cow_mapping(
 	*imap = irec;
 	*need_alloc = !!(isnullstartblock(irec.br_startblock));
 
-	return 0;
+	return true;
 }
 
 /*
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 398e726..6519f19 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -30,8 +30,7 @@ extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip,
 		xfs_fileoff_t offset_fsb, xfs_fileoff_t end_fsb);
 extern int xfs_reflink_allocate_cow_range(struct xfs_inode *ip, xfs_off_t pos,
 		xfs_off_t len);
-extern bool xfs_reflink_is_cow_pending(struct xfs_inode *ip, xfs_off_t offset);
-extern int xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset,
+extern bool xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset,
 		struct xfs_bmbt_irec *imap, bool *need_alloc);
 extern int xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip,
 		xfs_fileoff_t offset_fsb, struct xfs_bmbt_irec *imap);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux