|
@@ -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;
|