Message ID | 20241008085939.266014-7-hch@lst.de (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [01/10] iomap: factor out a iomap_last_written_block helper | expand |
On Tue, Oct 08, 2024 at 10:59:17AM +0200, Christoph Hellwig wrote: > 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> Thanks for fixing the bug I reported, Reviewed-by: Darrick J. Wong <djwong@kernel.org> --D > --- > fs/xfs/xfs_iomap.c | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c > index 4fa4d66dc37761..17170d9b9ff78a 100644 > --- a/fs/xfs/xfs_iomap.c > +++ b/fs/xfs/xfs_iomap.c > @@ -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; > } > > -- > 2.45.2 > >
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 4fa4d66dc37761..17170d9b9ff78a 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -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; }
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> --- fs/xfs/xfs_iomap.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)