summaryrefslogtreecommitdiff
path: root/fs/iomap
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2024-09-10 07:39:03 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-10-10 11:57:39 +0200
commit390b9e54cdfd6bb2cf3286db77691f2fd391aafe (patch)
tree78ac824a26912141ca18a2692fc5488c7ebfa2b9 /fs/iomap
parentad762c52047180c18386f177701a3ae6811de959 (diff)
downloadlinux-390b9e54cdfd6bb2cf3286db77691f2fd391aafe.tar.gz
linux-390b9e54cdfd6bb2cf3286db77691f2fd391aafe.tar.bz2
linux-390b9e54cdfd6bb2cf3286db77691f2fd391aafe.zip
iomap: handle a post-direct I/O invalidate race in iomap_write_delalloc_release
[ Upstream commit 7a9d43eace888a0ee6095035997bb138425844d3 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/iomap')
-rw-r--r--fs/iomap/buffered-io.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 5371b16341ff..aedaad4c37d7 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -1177,7 +1177,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,