From: Nanzhe <[email protected]> The original f2fs_read_data_large_folio() implementation has limited benefit with a 4KB block size, mainly because updating read_pages_pending greatly increases the number of spinlock operations.
Use len_blks to batch read_pages_pending and iostat updates for contiguous mapped blocks. If the contiguous mapping covers the whole folio, skip f2fs_folio_state allocation for that folio. Signed-off-by: Nanzhe <[email protected]> --- fs/f2fs/data.c | 55 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 033b28be2ae7..f02637e3f420 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -156,7 +156,7 @@ static void f2fs_finish_read_bio(struct bio *bio, bool in_task) continue; } - if (folio_test_large(folio)) { + if (folio_has_ffs(folio)) { struct f2fs_folio_state *ffs = folio->private; spin_lock_irqsave(&ffs->state_lock, flags); @@ -3012,7 +3012,7 @@ static int f2fs_read_data_large_folio(struct inode *inode, pgoff_t index, offset, next_pgofs = 0; unsigned max_nr_pages = rac ? readahead_count(rac) : folio_nr_pages(folio); - unsigned nrpages; + unsigned int nrpages, len_blks; struct f2fs_folio_state *ffs; int ret = 0; bool folio_in_bio = false; @@ -3039,8 +3039,15 @@ static int f2fs_read_data_large_folio(struct inode *inode, ffs = NULL; nrpages = folio_nr_pages(folio); - for (; nrpages; nrpages--, max_nr_pages--, index++, offset++) { + for (; nrpages; + nrpages -= len_blks, max_nr_pages -= len_blks, + index += len_blks, offset += len_blks) { sector_t block_nr; + bool whole_folio_in_bio; + unsigned int i; + + len_blks = 1; + /* * Map blocks using the previous result first. */ @@ -3069,13 +3076,31 @@ static int f2fs_read_data_large_folio(struct inode *inode, got_it: if ((map.m_flags & F2FS_MAP_MAPPED)) { block_nr = map.m_pblk + index - map.m_lblk; - if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr, + + len_blks = min_t(unsigned int, nrpages, max_nr_pages); + len_blks = min_t(unsigned int, len_blks, + (unsigned int)(map.m_lblk + map.m_len - index)); + + for (i = 0; i < len_blks; i++) { + if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), + block_nr + i, DATA_GENERIC_ENHANCE_READ)) { - ret = -EFSCORRUPTED; - goto err_out; + ret = -EFSCORRUPTED; + goto err_out; + } } + + /* + * If an entire folio is added to one bio, + * folio_end_read() can complete the folio read status + * without relying on f2fs_folio_state. + */ + whole_folio_in_bio = offset == 0 && + len_blks == folio_nr_pages(folio); + } else { size_t page_offset = offset << PAGE_SHIFT; + folio_zero_range(folio, page_offset, PAGE_SIZE); if (vi && !fsverity_verify_blocks(vi, folio, PAGE_SIZE, page_offset)) { ret = -EIO; @@ -3085,14 +3110,14 @@ static int f2fs_read_data_large_folio(struct inode *inode, } /* We must increment read_pages_pending before possible BIOs submitting - * to prevent from premature folio_end_read() call on folio + * to prevent from premature folio_end_read() call on folio. */ - if (folio_test_large(folio)) { + if (folio_test_large(folio) && !whole_folio_in_bio) { ffs = ffs_find_or_alloc(folio); /* set the bitmap to wait */ spin_lock_irq(&ffs->state_lock); - ffs->read_pages_pending++; + ffs->read_pages_pending += len_blks; spin_unlock_irq(&ffs->state_lock); } @@ -3117,17 +3142,19 @@ static int f2fs_read_data_large_folio(struct inode *inode, * If the page is under writeback, we need to wait for * its completion to see the correct decrypted data. */ - f2fs_wait_on_block_writeback(inode, block_nr); + for (i = 0; i < len_blks; i++) + f2fs_wait_on_block_writeback(inode, block_nr + i); - if (!bio_add_folio(bio, folio, F2FS_BLKSIZE, + if (!bio_add_folio(bio, folio, len_blks * F2FS_BLKSIZE, offset << PAGE_SHIFT)) goto submit_and_realloc; folio_in_bio = true; - inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); + for (i = 0; i < len_blks; i++) + inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO, - F2FS_BLKSIZE); - last_block_in_bio = block_nr; + len_blks * F2FS_BLKSIZE); + last_block_in_bio = block_nr + len_blks - 1; } trace_f2fs_read_folio(folio, DATA); err_out: -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
