@@ -488,6 +488,54 @@ check_writeio:
return alloc_blocks;
}
+/*
+ * If we are doing a write at the end of the file and there are no allocations
+ * past this one, then extend the allocation out to the file system's write
+ * iosize.
+ *
+ * As an exception we don't do any preallocation at all if the file is smaller
+ * than the minimum preallocation and we are using the default dynamic
+ * preallocation scheme, as it is likely this is the only write to the file that
+ * is going to be done.
+ *
+ * We clean up any extra space left over when the file is closed in
+ * xfs_inactive().
+ */
+static int
+xfs_iomap_prealloc(
+ struct xfs_inode *ip,
+ loff_t offset,
+ loff_t count,
+ xfs_extnum_t idx,
+ struct xfs_bmbt_irec *prev)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_fsblock_t alloc_blocks;
+ xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
+
+ if (offset + count <= XFS_ISIZE(ip))
+ return 0;
+
+ if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) &&
+ (XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, mp->m_writeio_blocks)))
+ return 0;
+
+ /*
+ * If an explicit allocsize is set, the file is small, or we
+ * are writing behind a hole, then use the minimum prealloc:
+ */
+ if ((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ||
+ XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, mp->m_dalign) ||
+ idx == 0 ||
+ prev->br_startoff + prev->br_blockcount < offset_fsb)
+ alloc_blocks = mp->m_writeio_blocks;
+ else
+ alloc_blocks =
+ xfs_iomap_prealloc_size(ip, offset, prev);
+
+ return alloc_blocks;
+}
+
static int
xfs_file_iomap_begin_delay(
struct inode *inode,
@@ -507,6 +555,7 @@ xfs_file_iomap_begin_delay(
struct xfs_bmbt_irec got;
struct xfs_bmbt_irec prev;
xfs_extnum_t idx;
+ xfs_fsblock_t prealloc = 0;
ASSERT(!XFS_IS_REALTIME_INODE(ip));
ASSERT(!xfs_get_extsz_hint(ip));
@@ -554,41 +603,14 @@ xfs_file_iomap_begin_delay(
end_fsb = orig_end_fsb =
min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
- /*
- * If we are doing a write at the end of the file and there are no
- * allocations past this one, then extend the allocation out to the
- * file system's write iosize.
- *
- * As an exception we don't do any preallocation at all if the file
- * is smaller than the minimum preallocation and we are using the
- * default dynamic preallocation scheme, as it is likely this is the
- * only write to the file that is going to be done.
- *
- * We clean up any extra space left over when the file is closed in
- * xfs_inactive().
- */
- if (eof && offset + count > XFS_ISIZE(ip) &&
- ((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ||
- XFS_ISIZE(ip) >= XFS_FSB_TO_B(mp, mp->m_writeio_blocks))) {
- xfs_fsblock_t alloc_blocks;
- xfs_off_t aligned_offset;
- xfs_extlen_t align;
-
- /*
- * If an explicit allocsize is set, the file is small, or we
- * are writing behind a hole, then use the minimum prealloc:
- */
- if ((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ||
- XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, mp->m_dalign) ||
- idx == 0 ||
- prev.br_startoff + prev.br_blockcount < offset_fsb)
- alloc_blocks = mp->m_writeio_blocks;
- else
- alloc_blocks =
- xfs_iomap_prealloc_size(ip, offset, &prev);
+ if (eof)
+ prealloc = xfs_iomap_prealloc(ip, offset, count, idx, &prev);
+ if (prealloc) {
+ xfs_off_t aligned_offset;
+ xfs_extlen_t align;
aligned_offset = XFS_WRITEIO_ALIGN(mp, offset + count - 1);
- end_fsb = XFS_B_TO_FSBT(mp, aligned_offset) + alloc_blocks;
+ end_fsb = XFS_B_TO_FSBT(mp, aligned_offset) + prealloc;
align = xfs_eof_alignment(ip, 0);
if (align)