Commit ffb375a8 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong
Browse files

xfs: pass two imaps to xfs_reflink_allocate_cow



xfs_reflink_allocate_cow consumes the source data fork imap, and
potentially returns the COW fork imap.  Split the arguments in two
to clear up the calling conventions and to prepare for returning
a source iomap from ->iomap_begin.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent dd26b846
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -996,9 +996,8 @@ xfs_file_iomap_begin(
			goto out_found;

		/* may drop and re-acquire the ilock */
		cmap = imap;
		error = xfs_reflink_allocate_cow(ip, &cmap, &shared, &lockmode,
				directio);
		error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
				&lockmode, directio);
		if (error)
			goto out_unlock;

@@ -1011,7 +1010,8 @@ xfs_file_iomap_begin(
		 * newly allocated address.  If the data fork has a hole, copy
		 * the COW fork mapping to avoid allocating to the data fork.
		 */
		if (directio || imap.br_startblock == HOLESTARTBLOCK)
		if (shared &&
		    (directio || imap.br_startblock == HOLESTARTBLOCK))
			imap = cmap;

		end_fsb = imap.br_startoff + imap.br_blockcount;
+15 −15
Original line number Diff line number Diff line
@@ -308,13 +308,13 @@ static int
xfs_find_trim_cow_extent(
	struct xfs_inode	*ip,
	struct xfs_bmbt_irec	*imap,
	struct xfs_bmbt_irec	*cmap,
	bool			*shared,
	bool			*found)
{
	xfs_fileoff_t		offset_fsb = imap->br_startoff;
	xfs_filblks_t		count_fsb = imap->br_blockcount;
	struct xfs_iext_cursor	icur;
	struct xfs_bmbt_irec	got;

	*found = false;

@@ -322,23 +322,22 @@ xfs_find_trim_cow_extent(
	 * If we don't find an overlapping extent, trim the range we need to
	 * allocate to fit the hole we found.
	 */
	if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got))
		got.br_startoff = offset_fsb + count_fsb;
	if (got.br_startoff > offset_fsb) {
	if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, cmap))
		cmap->br_startoff = offset_fsb + count_fsb;
	if (cmap->br_startoff > offset_fsb) {
		xfs_trim_extent(imap, imap->br_startoff,
				got.br_startoff - imap->br_startoff);
				cmap->br_startoff - imap->br_startoff);
		return xfs_inode_need_cow(ip, imap, shared);
	}

	*shared = true;
	if (isnullstartblock(got.br_startblock)) {
		xfs_trim_extent(imap, got.br_startoff, got.br_blockcount);
	if (isnullstartblock(cmap->br_startblock)) {
		xfs_trim_extent(imap, cmap->br_startoff, cmap->br_blockcount);
		return 0;
	}

	/* real extent found - no need to allocate */
	xfs_trim_extent(&got, offset_fsb, count_fsb);
	*imap = got;
	xfs_trim_extent(cmap, offset_fsb, count_fsb);
	*found = true;
	return 0;
}
@@ -348,6 +347,7 @@ int
xfs_reflink_allocate_cow(
	struct xfs_inode	*ip,
	struct xfs_bmbt_irec	*imap,
	struct xfs_bmbt_irec	*cmap,
	bool			*shared,
	uint			*lockmode,
	bool			convert_now)
@@ -367,7 +367,7 @@ xfs_reflink_allocate_cow(
		xfs_ifork_init_cow(ip);
	}

	error = xfs_find_trim_cow_extent(ip, imap, shared, &found);
	error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found);
	if (error || !*shared)
		return error;
	if (found)
@@ -392,7 +392,7 @@ xfs_reflink_allocate_cow(
	/*
	 * Check for an overlapping extent again now that we dropped the ilock.
	 */
	error = xfs_find_trim_cow_extent(ip, imap, shared, &found);
	error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found);
	if (error || !*shared)
		goto out_trans_cancel;
	if (found) {
@@ -411,7 +411,7 @@ xfs_reflink_allocate_cow(
	nimaps = 1;
	error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount,
			XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC,
			resblks, imap, &nimaps);
			resblks, cmap, &nimaps);
	if (error)
		goto out_unreserve;

@@ -427,15 +427,15 @@ xfs_reflink_allocate_cow(
	if (nimaps == 0)
		return -ENOSPC;
convert:
	xfs_trim_extent(imap, offset_fsb, count_fsb);
	xfs_trim_extent(cmap, offset_fsb, count_fsb);
	/*
	 * COW fork extents are supposed to remain unwritten until we're ready
	 * to initiate a disk write.  For direct I/O we are going to write the
	 * data and need the conversion, but for buffered writes we're done.
	 */
	if (!convert_now || imap->br_state == XFS_EXT_NORM)
	if (!convert_now || cmap->br_state == XFS_EXT_NORM)
		return 0;
	trace_xfs_reflink_convert_cow(ip, imap);
	trace_xfs_reflink_convert_cow(ip, cmap);
	return xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb);

out_unreserve:
+2 −2
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
bool xfs_inode_need_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap,
		bool *shared);

extern int xfs_reflink_allocate_cow(struct xfs_inode *ip,
		struct xfs_bmbt_irec *imap, bool *shared, uint *lockmode,
int xfs_reflink_allocate_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *imap,
		struct xfs_bmbt_irec *cmap, bool *shared, uint *lockmode,
		bool convert_now);
extern int xfs_reflink_convert_cow(struct xfs_inode *ip, xfs_off_t offset,
		xfs_off_t count);