]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iomap: handle a post-direct I/O invalidate race in iomap_write_delalloc_release
authorChristoph Hellwig <hch@lst.de>
Tue, 10 Sep 2024 04:39:03 +0000 (07:39 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2024 10:00:40 +0000 (12:00 +0200)
[ 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>
fs/iomap/buffered-io.c

index e817564e80e010cc3f6d05c6e37024fcc737429b..b9b035a5e7793b469a4c7bff97d4fad5c7bbcf3b 100644 (file)
@@ -1226,7 +1226,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,