Skip to content

Commit

Permalink
xfs: fill out the srcmap in iomap_begin
Browse files Browse the repository at this point in the history
Replace our local hacks to report the source block in the main iomap
with the proper scrmap reporting.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
  • Loading branch information
Christoph Hellwig authored and djwong committed Oct 21, 2019
1 parent ae36b53 commit 36adcba
Showing 1 changed file with 24 additions and 25 deletions.
49 changes: 24 additions & 25 deletions fs/xfs/xfs_iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,8 @@ xfs_file_iomap_begin_delay(
loff_t offset,
loff_t count,
unsigned flags,
struct iomap *iomap)
struct iomap *iomap,
struct iomap *srcmap)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
Expand Down Expand Up @@ -721,11 +722,13 @@ xfs_file_iomap_begin_delay(
found_cow:
xfs_iunlock(ip, XFS_ILOCK_EXCL);
if (imap.br_startoff <= offset_fsb) {
/* ensure we only report blocks we have a reservation for */
xfs_trim_extent(&imap, cmap.br_startoff, cmap.br_blockcount);
return xfs_bmbt_to_iomap(ip, iomap, &imap, IOMAP_F_SHARED);
error = xfs_bmbt_to_iomap(ip, srcmap, &imap, 0);
if (error)
return error;
} else {
xfs_trim_extent(&cmap, offset_fsb,
imap.br_startoff - offset_fsb);
}
xfs_trim_extent(&cmap, offset_fsb, imap.br_startoff - offset_fsb);
return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);

out_unlock:
Expand Down Expand Up @@ -933,7 +936,7 @@ xfs_file_iomap_begin(
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
struct xfs_bmbt_irec imap;
struct xfs_bmbt_irec imap, cmap;
xfs_fileoff_t offset_fsb, end_fsb;
int nimaps = 1, error = 0;
bool shared = false;
Expand All @@ -947,7 +950,7 @@ xfs_file_iomap_begin(
!IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
/* Reserve delalloc blocks for regular writeback. */
return xfs_file_iomap_begin_delay(inode, offset, length, flags,
iomap);
iomap, srcmap);
}

/*
Expand Down Expand Up @@ -987,33 +990,18 @@ xfs_file_iomap_begin(
* been done up front, so we don't need to do them here.
*/
if (xfs_is_cow_inode(ip)) {
struct xfs_bmbt_irec cmap;
bool directio = (flags & IOMAP_DIRECT);

/* if zeroing doesn't need COW allocation, then we are done. */
if ((flags & IOMAP_ZERO) &&
!needs_cow_for_zeroing(&imap, nimaps))
goto out_found;

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

/*
* For buffered writes we need to report the address of the
* previous block (if there was any) so that the higher level
* write code can perform read-modify-write operations; we
* won't need the CoW fork mapping until writeback. For direct
* I/O, which must be block aligned, we need to report the
* newly allocated address. If the data fork has a hole, copy
* the COW fork mapping to avoid allocating to the data fork.
*/
if (shared &&
(directio || imap.br_startblock == HOLESTARTBLOCK))
imap = cmap;

if (shared)
goto out_found_cow;
end_fsb = imap.br_startoff + imap.br_blockcount;
length = XFS_FSB_TO_B(mp, end_fsb) - offset;
}
Expand Down Expand Up @@ -1074,6 +1062,17 @@ xfs_file_iomap_begin(
trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
goto out_finish;

out_found_cow:
xfs_iunlock(ip, lockmode);
length = XFS_FSB_TO_B(mp, cmap.br_startoff + cmap.br_blockcount);
trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
if (imap.br_startblock != HOLESTARTBLOCK) {
error = xfs_bmbt_to_iomap(ip, srcmap, &imap, 0);
if (error)
return error;
}
return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);

out_unlock:
xfs_iunlock(ip, lockmode);
return error;
Expand Down

0 comments on commit 36adcba

Please sign in to comment.