Skip to content

Commit c2888c4

Browse files
Andreas Gruenbachergregkh
authored andcommitted
gfs2: Don't get stuck writing page onto itself under direct I/O
[ Upstream commit fa58cc8 ] When a direct I/O write is performed, iomap_dio_rw() invalidates the part of the page cache which the write is going to before carrying out the write. In the odd case, the direct I/O write will be reading from the same page it is writing to. gfs2 carries out writes with page faults disabled, so it should have been obvious that this page invalidation can cause iomap_dio_rw() to never make any progress. Currently, gfs2 will end up in an endless retry loop in gfs2_file_direct_write() instead, though. Break this endless loop by limiting the number of retries and falling back to buffered I/O after that. Also simplify should_fault_in_pages() sightly and add a comment to make the above case easier to understand. Reported-by: Jan Kara <[email protected]> Signed-off-by: Andreas Gruenbacher <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 878dad6 commit c2888c4

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

fs/gfs2/file.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,9 +783,13 @@ static inline bool should_fault_in_pages(struct iov_iter *i,
783783
if (!user_backed_iter(i))
784784
return false;
785785

786+
/*
787+
* Try to fault in multiple pages initially. When that doesn't result
788+
* in any progress, fall back to a single page.
789+
*/
786790
size = PAGE_SIZE;
787791
offs = offset_in_page(iocb->ki_pos);
788-
if (*prev_count != count || !*window_size) {
792+
if (*prev_count != count) {
789793
size_t nr_dirtied;
790794

791795
nr_dirtied = max(current->nr_dirtied_pause -
@@ -869,6 +873,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
869873
struct gfs2_inode *ip = GFS2_I(inode);
870874
size_t prev_count = 0, window_size = 0;
871875
size_t written = 0;
876+
bool enough_retries;
872877
ssize_t ret;
873878

874879
/*
@@ -912,11 +917,17 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
912917
if (ret > 0)
913918
written = ret;
914919

920+
enough_retries = prev_count == iov_iter_count(from) &&
921+
window_size <= PAGE_SIZE;
915922
if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
916923
gfs2_glock_dq(gh);
917924
window_size -= fault_in_iov_iter_readable(from, window_size);
918-
if (window_size)
919-
goto retry;
925+
if (window_size) {
926+
if (!enough_retries)
927+
goto retry;
928+
/* fall back to buffered I/O */
929+
ret = 0;
930+
}
920931
}
921932
out_unlock:
922933
if (gfs2_holder_queued(gh))

0 commit comments

Comments
 (0)