xfs: take XFS_MMAPLOCK_EXCL xfs_file_write_zero_eof
authorChristoph Hellwig <hch@lst.de>
Tue, 8 Oct 2024 08:59:16 +0000 (10:59 +0200)
committerCarlos Maiolino <cem@kernel.org>
Tue, 15 Oct 2024 09:37:42 +0000 (11:37 +0200)
xfs_file_write_zero_eof is the only caller of xfs_zero_range that does
not take XFS_MMAPLOCK_EXCL (aka the invalidate lock).  Currently that
is actually the right thing, as an error in the iomap zeroing code will
also take the invalidate_lock to clean up, but to fix that deadlock we
need a consistent locking pattern first.

The only extra thing that XFS_MMAPLOCK_EXCL will lock out are read
pagefaults, which isn't really needed here, but also not actively
harmful.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/xfs_file.c
fs/xfs/xfs_iomap.c

index 3efb0da..b19916b 100644 (file)
@@ -364,6 +364,7 @@ xfs_file_write_zero_eof(
 {
        struct xfs_inode        *ip = XFS_I(iocb->ki_filp->f_mapping->host);
        loff_t                  isize;
+       int                     error;
 
        /*
         * We need to serialise against EOF updates that occur in IO completions
@@ -411,7 +412,12 @@ xfs_file_write_zero_eof(
        }
 
        trace_xfs_zero_eof(ip, isize, iocb->ki_pos - isize);
-       return xfs_zero_range(ip, isize, iocb->ki_pos - isize, NULL);
+
+       xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
+       error = xfs_zero_range(ip, isize, iocb->ki_pos - isize, NULL);
+       xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
+
+       return error;
 }
 
 /*
index 01324da..4fa4d66 100644 (file)
@@ -1449,6 +1449,8 @@ xfs_zero_range(
 {
        struct inode            *inode = VFS_I(ip);
 
+       xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
+
        if (IS_DAX(inode))
                return dax_zero_range(inode, pos, len, did_zero,
                                      &xfs_dax_write_iomap_ops);