xfs: simplify xfs_file_iomap_begin() logic

The current logic that determines whether allocation should be done
has grown somewhat spaghetti like with the addition of IOMAP_NOWAIT
functionality. Separate out each of the different cases into single,
obvious checks to get rid most of the nested IOMAP_NOWAIT checks
in the allocation logic.

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-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>
This commit is contained in:
Dave Chinner 2018-05-02 12:54:53 -07:00 committed by Darrick J. Wong
parent 3460cac1ca
commit d064178094

View File

@ -1040,6 +1040,10 @@ xfs_file_iomap_begin(
goto out_unlock;
}
/* Non-modifying mapping requested, so we are done */
if (!(flags & (IOMAP_WRITE | IOMAP_ZERO)))
goto out_found;
if (xfs_is_reflink_inode(ip) &&
((flags & IOMAP_WRITE) ||
((flags & IOMAP_ZERO) && needs_cow_for_zeroing(&imap, nimaps)))) {
@ -1068,46 +1072,45 @@ xfs_file_iomap_begin(
length = XFS_FSB_TO_B(mp, end_fsb) - offset;
}
if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
/*
* If nowait is set bail since we are going to make
* allocations.
*/
if (flags & IOMAP_NOWAIT) {
error = -EAGAIN;
goto out_unlock;
}
/*
* We cap the maximum length we map here to MAX_WRITEBACK_PAGES
* pages to keep the chunks of work done where somewhat symmetric
* with the work writeback does. This is a completely arbitrary
* number pulled out of thin air as a best guess for initial
* testing.
*
* Note that the values needs to be less than 32-bits wide until
* the lower level functions are updated.
*/
length = min_t(loff_t, length, 1024 * PAGE_SIZE);
/*
* xfs_iomap_write_direct() expects the shared lock. It
* is unlocked on return.
*/
if (lockmode == XFS_ILOCK_EXCL)
xfs_ilock_demote(ip, lockmode);
error = xfs_iomap_write_direct(ip, offset, length, &imap,
nimaps);
if (error)
return error;
/* Don't need to allocate over holes when doing zeroing operations. */
if (flags & IOMAP_ZERO)
goto out_found;
iomap->flags = IOMAP_F_NEW;
trace_xfs_iomap_alloc(ip, offset, length, 0, &imap);
} else {
ASSERT(nimaps);
if (!imap_needs_alloc(inode, &imap, nimaps))
goto out_found;
xfs_iunlock(ip, lockmode);
trace_xfs_iomap_found(ip, offset, length, 0, &imap);
/* If nowait is set bail since we are going to make allocations. */
if (flags & IOMAP_NOWAIT) {
error = -EAGAIN;
goto out_unlock;
}
/*
* We cap the maximum length we map to a sane size to keep the chunks
* of work done where somewhat symmetric with the work writeback does.
* This is a completely arbitrary number pulled out of thin air as a
* best guess for initial testing.
*
* Note that the values needs to be less than 32-bits wide until the
* lower level functions are updated.
*/
length = min_t(loff_t, length, 1024 * PAGE_SIZE);
/*
* xfs_iomap_write_direct() expects the shared lock. It is unlocked on
* return.
*/
if (lockmode == XFS_ILOCK_EXCL)
xfs_ilock_demote(ip, lockmode);
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, 0, &imap);
out_finish:
if (xfs_ipincount(ip) && (ip->i_itemp->ili_fsync_fields
& ~XFS_ILOG_TIMESTAMP))
iomap->flags |= IOMAP_F_DIRTY;
@ -1117,6 +1120,13 @@ xfs_file_iomap_begin(
if (shared)
iomap->flags |= IOMAP_F_SHARED;
return 0;
out_found:
ASSERT(nimaps);
xfs_iunlock(ip, lockmode);
trace_xfs_iomap_found(ip, offset, length, 0, &imap);
goto out_finish;
out_unlock:
xfs_iunlock(ip, lockmode);
return error;