From: Chi Zhiling Date: Fri, 29 Aug 2025 02:36:58 +0000 (+0800) Subject: mpage: terminate read-ahead on read error X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=72492759d13b0109f34d42d784defd095753929a;p=users%2Fjedix%2Flinux-maple.git mpage: terminate read-ahead on read error For exFAT filesystems with 4MB read_ahead_size, removing the storage device during read operations can delay EIO error reporting by several minutes. This occurs because the read-ahead implementation in mpage doesn't handle errors. Another reason for the delay is that the filesystem requires metadata to issue file read request. When the storage device is removed, the metadata buffers are invalidated, causing mpage to repeatedly attempt to fetch metadata during each get_block call. The original purpose of this patch is terminate read ahead when we fail to get metadata, to make the patch more generic, implement it by checking folio status, instead of checking the return of get_block(). So, if a folio is synchronously unlocked and non-uptodate, should we quit the read ahead? I think it depends on whether the error is permanent or temporary, and whether further read ahead might succeed. A device being unplugged is one reason for returning such a folio, but we could return it for many other reasons (e.g., metadata errors). I think most errors won't be restored in a short time, so we should quit read ahead when they occur. Link: https://lkml.kernel.org/r/20250829023659.688649-1-chizhiling@163.com Signed-off-by: Chi Zhiling Reviewed-by: Jan Kara Cc: Al Viro Cc: Christian Brauner Cc: Matthew Wilcox (Oracle) Cc: Namjae Jeon Cc: Sungjong Seo Cc: Yuezhang Mo Signed-off-by: Andrew Morton --- diff --git a/fs/mpage.c b/fs/mpage.c index c5fd821fd30e5..e4c11831f2341 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -369,6 +369,12 @@ void mpage_readahead(struct readahead_control *rac, get_block_t get_block) args.folio = folio; args.nr_pages = readahead_count(rac); args.bio = do_mpage_readpage(&args); + /* + * If read ahead failed synchronously, it may cause by removed + * device, or some filesystem metadata error. + */ + if (!folio_test_locked(folio) && !folio_test_uptodate(folio)) + break; } if (args.bio) mpage_bio_submit_read(args.bio);