xfs: IOMAP_ZERO and IOMAP_UNSHARE already hold invalidate_lock
authorChristoph Hellwig <hch@lst.de>
Tue, 8 Oct 2024 08:59:17 +0000 (10:59 +0200)
committerCarlos Maiolino <cem@kernel.org>
Tue, 15 Oct 2024 09:37:42 +0000 (11:37 +0200)
All XFS callers of iomap_zero_range and iomap_file_unshare already hold
invalidate_lock, so we can't take it again in
iomap_file_buffered_write_punch_delalloc.

Use the passed in flags argument to detect if we're called from a zero
or unshare operation and don't take the lock again in this case.

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_iomap.c

index 4fa4d66..17170d9 100644 (file)
@@ -1239,10 +1239,18 @@ xfs_buffered_write_iomap_end(
        if (start_byte >= end_byte)
                return 0;
 
-       filemap_invalidate_lock(inode->i_mapping);
-       iomap_write_delalloc_release(inode, start_byte, end_byte, flags, iomap,
-                       xfs_buffered_write_delalloc_punch);
-       filemap_invalidate_unlock(inode->i_mapping);
+       /* For zeroing operations the callers already hold invalidate_lock. */
+       if (flags & (IOMAP_UNSHARE | IOMAP_ZERO)) {
+               rwsem_assert_held_write(&inode->i_mapping->invalidate_lock);
+               iomap_write_delalloc_release(inode, start_byte, end_byte, flags,
+                               iomap, xfs_buffered_write_delalloc_punch);
+       } else {
+               filemap_invalidate_lock(inode->i_mapping);
+               iomap_write_delalloc_release(inode, start_byte, end_byte, flags,
+                               iomap, xfs_buffered_write_delalloc_punch);
+               filemap_invalidate_unlock(inode->i_mapping);
+       }
+
        return 0;
 }