]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
xfs: factor out isize updates from xfs_dio_write_end_io
authorCarlos Maiolino <cem@kernel.org>
Tue, 10 Mar 2026 17:36:46 +0000 (18:36 +0100)
committerCarlos Maiolino <cem@kernel.org>
Thu, 12 Mar 2026 07:49:36 +0000 (08:49 +0100)
This is the only code needed for zoned inodes, so factor it out so
we can move zoned inodes ioend to its own callback.

Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/xfs_file.c

index 6246f34df9fd165ec91161532ea742990e46040e..fce6be55d90cbd291e5cea6f72fe90e91a7b08a0 100644 (file)
@@ -560,6 +560,42 @@ xfs_zoned_write_space_reserve(
                        flags, ac);
 }
 
+/*
+ * We need to lock the test/set EOF update as we can be racing with
+ * other IO completions here to update the EOF. Failing to serialise
+ * here can result in EOF moving backwards and Bad Things Happen when
+ * that occurs.
+ *
+ * As IO completion only ever extends EOF, we can do an unlocked check
+ * here to avoid taking the spinlock. If we land within the current EOF,
+ * then we do not need to do an extending update at all, and we don't
+ * need to take the lock to check this. If we race with an update moving
+ * EOF, then we'll either still be beyond EOF and need to take the lock,
+ * or we'll be within EOF and we don't need to take it at all.
+ */
+static int
+xfs_dio_endio_set_isize(
+       struct inode            *inode,
+       loff_t                  offset,
+       ssize_t                 size)
+{
+       struct xfs_inode        *ip = XFS_I(inode);
+
+       if (offset + size <= i_size_read(inode))
+               return 0;
+
+       spin_lock(&ip->i_flags_lock);
+       if (offset + size <= i_size_read(inode)) {
+               spin_unlock(&ip->i_flags_lock);
+               return 0;
+       }
+
+       i_size_write(inode, offset + size);
+       spin_unlock(&ip->i_flags_lock);
+
+       return xfs_setfilesize(ip, offset, size);
+}
+
 static int
 xfs_dio_write_end_io(
        struct kiocb            *iocb,
@@ -623,30 +659,8 @@ xfs_dio_write_end_io(
         * with the on-disk inode size being outside the in-core inode size. We
         * have no other method of updating EOF for AIO, so always do it here
         * if necessary.
-        *
-        * We need to lock the test/set EOF update as we can be racing with
-        * other IO completions here to update the EOF. Failing to serialise
-        * here can result in EOF moving backwards and Bad Things Happen when
-        * that occurs.
-        *
-        * As IO completion only ever extends EOF, we can do an unlocked check
-        * here to avoid taking the spinlock. If we land within the current EOF,
-        * then we do not need to do an extending update at all, and we don't
-        * need to take the lock to check this. If we race with an update moving
-        * EOF, then we'll either still be beyond EOF and need to take the lock,
-        * or we'll be within EOF and we don't need to take it at all.
         */
-       if (offset + size <= i_size_read(inode))
-               goto out;
-
-       spin_lock(&ip->i_flags_lock);
-       if (offset + size > i_size_read(inode)) {
-               i_size_write(inode, offset + size);
-               spin_unlock(&ip->i_flags_lock);
-               error = xfs_setfilesize(ip, offset, size);
-       } else {
-               spin_unlock(&ip->i_flags_lock);
-       }
+       error = xfs_dio_endio_set_isize(inode, offset, size);
 
 out:
        memalloc_nofs_restore(nofs_flag);