In f2fs_read_data_large_folio(), read_pages_pending is incremented only after the subpage has been added to the BIO. With a heavily fragmented file, each new subpage can force submission of the previous BIO.
If the BIO completes quickly, f2fs_finish_read_bio() may decrement read_pages_pending to zero and call folio_end_read() while the read loop is still processing other subpages of the same large folio. Fix the ordering by incrementing read_pages_pending before any possible BIO submission for the current subpage, matching the iomap ordering and preventing premature folio_end_read(). Signed-off-by: Nanzhe Zhao <[email protected]> --- fs/f2fs/data.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index ab091b294fa7..4bef04560924 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2486,6 +2486,18 @@ static int f2fs_read_data_large_folio(struct inode *inode, continue; } + /* We must increment read_pages_pending before possible BIOs submitting + * to prevent from premature folio_end_read() call on folio + */ + if (folio_test_large(folio)) { + ffs = ffs_find_or_alloc(folio); + + /* set the bitmap to wait */ + spin_lock_irq(&ffs->state_lock); + ffs->read_pages_pending++; + spin_unlock_irq(&ffs->state_lock); + } + /* * This page will go to BIO. Do we need to send this * BIO off first? @@ -2513,15 +2525,6 @@ static int f2fs_read_data_large_folio(struct inode *inode, offset << PAGE_SHIFT)) goto submit_and_realloc; - if (folio_test_large(folio)) { - ffs = ffs_find_or_alloc(folio); - - /* set the bitmap to wait */ - spin_lock_irq(&ffs->state_lock); - ffs->read_pages_pending++; - spin_unlock_irq(&ffs->state_lock); - } - inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO, F2FS_BLKSIZE); -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
