diff options
author | Christoph Hellwig <hch@lst.de> | 2024-09-10 07:39:03 +0300 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2024-09-10 11:13:43 +0200 |
commit | 7a9d43eace888a0ee6095035997bb138425844d3 (patch) | |
tree | 80c7d87ec277ebac8f00a13f3f80f088e79e7973 /fs/iomap | |
parent | b1daf3f8475fa2a4ffc1668043de738241f95d1d (diff) | |
download | linux-7a9d43eace888a0ee6095035997bb138425844d3.tar.gz linux-7a9d43eace888a0ee6095035997bb138425844d3.tar.bz2 linux-7a9d43eace888a0ee6095035997bb138425844d3.zip |
iomap: handle a post-direct I/O invalidate race in iomap_write_delalloc_release
When direct I/O completions invalidates the page cache it holds neither the
i_rwsem nor the invalidate_lock so it can be racing with
iomap_write_delalloc_release. If the search for the end of the region that
contains data returns the start offset we hit such a race and just need to
look for the end of the newly created hole instead.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20240910043949.3481298-2-hch@lst.de
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/iomap')
-rw-r--r-- | fs/iomap/buffered-io.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index de47698a029a..db7a3ff92e61 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -1242,7 +1242,15 @@ static int iomap_write_delalloc_release(struct inode *inode, error = data_end; goto out_unlock; } - WARN_ON_ONCE(data_end <= start_byte); + + /* + * If we race with post-direct I/O invalidation of the page cache, + * there might be no data left at start_byte. + */ + if (data_end == start_byte) + continue; + + WARN_ON_ONCE(data_end < start_byte); WARN_ON_ONCE(data_end > scan_end_byte); error = iomap_write_delalloc_scan(inode, &punch_start_byte, |