Patch "gfs2: Don't get stuck writing page onto itself under direct I/O" has been added to the 6.3-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    gfs2: Don't get stuck writing page onto itself under direct I/O

to the 6.3-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     gfs2-don-t-get-stuck-writing-page-onto-itself-under-.patch
and it can be found in the queue-6.3 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 11f3922ee083480a0ed00cf3dacb4bfd8e3589e2
Author: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
Date:   Wed May 31 21:08:26 2023 +0200

    gfs2: Don't get stuck writing page onto itself under direct I/O
    
    [ Upstream commit fa58cc888d67e640e354d8b3ceef877ea167b0cf ]
    
    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 <jack@xxxxxxx>
    Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 300844f50dcd2..cb62c8f07d1e7 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -784,9 +784,13 @@ static inline bool should_fault_in_pages(struct iov_iter *i,
 	if (!user_backed_iter(i))
 		return false;
 
+	/*
+	 * Try to fault in multiple pages initially.  When that doesn't result
+	 * in any progress, fall back to a single page.
+	 */
 	size = PAGE_SIZE;
 	offs = offset_in_page(iocb->ki_pos);
-	if (*prev_count != count || !*window_size) {
+	if (*prev_count != count) {
 		size_t nr_dirtied;
 
 		nr_dirtied = max(current->nr_dirtied_pause -
@@ -870,6 +874,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
 	struct gfs2_inode *ip = GFS2_I(inode);
 	size_t prev_count = 0, window_size = 0;
 	size_t written = 0;
+	bool enough_retries;
 	ssize_t ret;
 
 	/*
@@ -913,11 +918,17 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
 	if (ret > 0)
 		written = ret;
 
+	enough_retries = prev_count == iov_iter_count(from) &&
+			 window_size <= PAGE_SIZE;
 	if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) {
 		gfs2_glock_dq(gh);
 		window_size -= fault_in_iov_iter_readable(from, window_size);
-		if (window_size)
-			goto retry;
+		if (window_size) {
+			if (!enough_retries)
+				goto retry;
+			/* fall back to buffered I/O */
+			ret = 0;
+		}
 	}
 out_unlock:
 	if (gfs2_holder_queued(gh))



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux