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

Reply via email to