]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
f2fs: fix missing read bio submission on large folio error
authorWenjie Qi <qiwenjie@xiaomi.com>
Wed, 20 May 2026 09:52:04 +0000 (17:52 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Mon, 22 Jun 2026 19:52:35 +0000 (19:52 +0000)
f2fs_read_data_large_folio() can keep a read bio across multiple
readahead folios.  If a later folio hits an error before any of its
blocks are added to the bio, folio_in_bio is false and the current error
path returns immediately after ending that folio.

This can leave the bio accumulated for earlier folios unsubmitted.  Those
folios then never receive read completion, and readers can wait
indefinitely on the locked folios.

Route errors through the common out path so any pending bio is submitted
before returning.  Stop consuming more readahead folios once an error is
seen, and only wait on and clear the current folio when it was actually
added to the bio.

Cc: stable@kernel.org
Fixes: a5d8b9d94e18 ("f2fs: fix to unlock folio in f2fs_read_data_large_folio()")
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c

index 5d18119a214a4c141456ef0ba94d5a9cad4afeef..d83a21998ec2d77d8db2a63e8954df28ae06c7d3 100644 (file)
@@ -2529,7 +2529,7 @@ static int f2fs_read_data_large_folio(struct inode *inode,
        unsigned nrpages;
        struct f2fs_folio_state *ffs;
        int ret = 0;
-       bool folio_in_bio;
+       bool folio_in_bio = false;
 
        if (!IS_IMMUTABLE(inode) || f2fs_compressed_file(inode)) {
                if (folio)
@@ -2645,18 +2645,17 @@ submit_and_realloc:
        }
        trace_f2fs_read_folio(folio, DATA);
 err_out:
-       if (!folio_in_bio) {
+       if (!folio_in_bio)
                folio_end_read(folio, !ret);
-               if (ret)
-                       return ret;
-       }
+       if (ret)
+               goto out;
        if (rac) {
                folio = readahead_folio(rac);
                goto next_folio;
        }
 out:
        f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA);
-       if (ret) {
+       if (ret && folio_in_bio) {
                /* Wait bios and clear uptodate. */
                folio_lock(folio);
                folio_clear_uptodate(folio);