From: Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net>
To: jaegeuk@kernel.org
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: [f2fs-dev] [PATCH] f2fs: avoid f2fs_map_blocks() for consecutive holes in readpages
Date: Mon, 12 Jan 2026 09:33:20 +0800 [thread overview]
Message-ID: <20260112013320.8028-1-chao@kernel.org> (raw)
For consecutive large hole mapping across {d,id,did}nodes , we don't
need to call f2fs_map_blocks() to check one hole block per one time,
instead, we can use map.m_next_pgofs as a hint of next potential valid
block, so that we can skip calling f2fs_map_blocks the range of
[cur_pgofs + 1, .m_next_pgofs).
1) regular case
touch /mnt/f2fs/file
truncate -s $((1024*1024*1024)) /mnt/f2fs/file
time dd if=/mnt/f2fs/file of=/dev/null bs=1M count=1024
Before:
real 0m0.706s
user 0m0.000s
sys 0m0.706s
After:
real 0m0.620s
user 0m0.008s
sys 0m0.611s
2) large folio case
touch /mnt/f2fs/file
truncate -s $((1024*1024*1024)) /mnt/f2fs/file
f2fs_io setflags immutable /mnt/f2fs/file
sync
echo 3 > /proc/sys/vm/drop_caches
time dd if=/mnt/f2fs/file of=/dev/null bs=1M count=1024
Before:
real 0m0.438s
user 0m0.004s
sys 0m0.433s
After:
real 0m0.368s
user 0m0.004s
sys 0m0.364s
Signed-off-by: Chao Yu <chao@kernel.org>
---
fs/f2fs/data.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a2c4769d0ae1..5b0642cd27ff 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2176,10 +2176,13 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
/*
* Map blocks using the previous result first.
*/
- if ((map->m_flags & F2FS_MAP_MAPPED) &&
- block_in_file > map->m_lblk &&
+ if (map->m_flags & F2FS_MAP_MAPPED) {
+ if (block_in_file > map->m_lblk &&
block_in_file < (map->m_lblk + map->m_len))
+ goto got_it;
+ } else if (block_in_file < *map->m_next_pgofs) {
goto got_it;
+ }
/*
* Then do more f2fs_map_blocks() calls until we are
@@ -2454,7 +2457,7 @@ static int f2fs_read_data_large_folio(struct inode *inode,
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
struct f2fs_map_blocks map = {0, };
- pgoff_t index, offset;
+ pgoff_t index, offset, next_pgofs = 0;
unsigned max_nr_pages = rac ? readahead_count(rac) :
folio_nr_pages(folio);
unsigned nrpages;
@@ -2487,16 +2490,21 @@ static int f2fs_read_data_large_folio(struct inode *inode,
/*
* Map blocks using the previous result first.
*/
- if ((map.m_flags & F2FS_MAP_MAPPED) &&
- index > map.m_lblk &&
+ if (map.m_flags & F2FS_MAP_MAPPED) {
+ if (index > map.m_lblk &&
index < (map.m_lblk + map.m_len))
+ goto got_it;
+ } else if (index < next_pgofs) {
+ /* hole case */
goto got_it;
+ }
/*
* Then do more f2fs_map_blocks() calls until we are
* done with this page.
*/
memset(&map, 0, sizeof(map));
+ map.m_next_pgofs = &next_pgofs;
map.m_seg_type = NO_CHECK_TYPE;
map.m_lblk = index;
map.m_len = max_nr_pages;
@@ -2617,6 +2625,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
pgoff_t nc_cluster_idx = NULL_CLUSTER;
pgoff_t index;
#endif
+ pgoff_t next_pgofs = 0;
unsigned nr_pages = rac ? readahead_count(rac) : 1;
struct address_space *mapping = rac ? rac->mapping : folio->mapping;
unsigned max_nr_pages = nr_pages;
@@ -2637,7 +2646,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
map.m_lblk = 0;
map.m_len = 0;
map.m_flags = 0;
- map.m_next_pgofs = NULL;
+ map.m_next_pgofs = &next_pgofs;
map.m_next_extent = NULL;
map.m_seg_type = NO_CHECK_TYPE;
map.m_may_create = false;
--
2.40.1
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
WARNING: multiple messages have this Message-ID (diff)
From: Chao Yu <chao@kernel.org>
To: jaegeuk@kernel.org
Cc: linux-f2fs-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org, Chao Yu <chao@kernel.org>
Subject: [PATCH] f2fs: avoid f2fs_map_blocks() for consecutive holes in readpages
Date: Mon, 12 Jan 2026 09:33:20 +0800 [thread overview]
Message-ID: <20260112013320.8028-1-chao@kernel.org> (raw)
For consecutive large hole mapping across {d,id,did}nodes , we don't
need to call f2fs_map_blocks() to check one hole block per one time,
instead, we can use map.m_next_pgofs as a hint of next potential valid
block, so that we can skip calling f2fs_map_blocks the range of
[cur_pgofs + 1, .m_next_pgofs).
1) regular case
touch /mnt/f2fs/file
truncate -s $((1024*1024*1024)) /mnt/f2fs/file
time dd if=/mnt/f2fs/file of=/dev/null bs=1M count=1024
Before:
real 0m0.706s
user 0m0.000s
sys 0m0.706s
After:
real 0m0.620s
user 0m0.008s
sys 0m0.611s
2) large folio case
touch /mnt/f2fs/file
truncate -s $((1024*1024*1024)) /mnt/f2fs/file
f2fs_io setflags immutable /mnt/f2fs/file
sync
echo 3 > /proc/sys/vm/drop_caches
time dd if=/mnt/f2fs/file of=/dev/null bs=1M count=1024
Before:
real 0m0.438s
user 0m0.004s
sys 0m0.433s
After:
real 0m0.368s
user 0m0.004s
sys 0m0.364s
Signed-off-by: Chao Yu <chao@kernel.org>
---
fs/f2fs/data.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a2c4769d0ae1..5b0642cd27ff 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2176,10 +2176,13 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
/*
* Map blocks using the previous result first.
*/
- if ((map->m_flags & F2FS_MAP_MAPPED) &&
- block_in_file > map->m_lblk &&
+ if (map->m_flags & F2FS_MAP_MAPPED) {
+ if (block_in_file > map->m_lblk &&
block_in_file < (map->m_lblk + map->m_len))
+ goto got_it;
+ } else if (block_in_file < *map->m_next_pgofs) {
goto got_it;
+ }
/*
* Then do more f2fs_map_blocks() calls until we are
@@ -2454,7 +2457,7 @@ static int f2fs_read_data_large_folio(struct inode *inode,
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
struct f2fs_map_blocks map = {0, };
- pgoff_t index, offset;
+ pgoff_t index, offset, next_pgofs = 0;
unsigned max_nr_pages = rac ? readahead_count(rac) :
folio_nr_pages(folio);
unsigned nrpages;
@@ -2487,16 +2490,21 @@ static int f2fs_read_data_large_folio(struct inode *inode,
/*
* Map blocks using the previous result first.
*/
- if ((map.m_flags & F2FS_MAP_MAPPED) &&
- index > map.m_lblk &&
+ if (map.m_flags & F2FS_MAP_MAPPED) {
+ if (index > map.m_lblk &&
index < (map.m_lblk + map.m_len))
+ goto got_it;
+ } else if (index < next_pgofs) {
+ /* hole case */
goto got_it;
+ }
/*
* Then do more f2fs_map_blocks() calls until we are
* done with this page.
*/
memset(&map, 0, sizeof(map));
+ map.m_next_pgofs = &next_pgofs;
map.m_seg_type = NO_CHECK_TYPE;
map.m_lblk = index;
map.m_len = max_nr_pages;
@@ -2617,6 +2625,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
pgoff_t nc_cluster_idx = NULL_CLUSTER;
pgoff_t index;
#endif
+ pgoff_t next_pgofs = 0;
unsigned nr_pages = rac ? readahead_count(rac) : 1;
struct address_space *mapping = rac ? rac->mapping : folio->mapping;
unsigned max_nr_pages = nr_pages;
@@ -2637,7 +2646,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
map.m_lblk = 0;
map.m_len = 0;
map.m_flags = 0;
- map.m_next_pgofs = NULL;
+ map.m_next_pgofs = &next_pgofs;
map.m_next_extent = NULL;
map.m_seg_type = NO_CHECK_TYPE;
map.m_may_create = false;
--
2.40.1
next reply other threads:[~2026-01-12 1:33 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-12 1:33 Chao Yu via Linux-f2fs-devel [this message]
2026-01-12 1:33 ` [PATCH] f2fs: avoid f2fs_map_blocks() for consecutive holes in readpages Chao Yu
2026-01-15 12:48 ` [f2fs-dev] " Nanzhe Zhao
2026-01-15 12:48 ` Nanzhe Zhao
2026-01-16 8:52 ` Chao Yu via Linux-f2fs-devel
2026-01-16 8:52 ` Chao Yu
2026-01-19 7:43 ` Nanzhe Zhao
2026-01-19 7:43 ` Nanzhe Zhao
2026-01-19 13:44 ` Chao Yu via Linux-f2fs-devel
2026-01-19 13:44 ` Chao Yu
2026-01-20 0:24 ` Nanzhe Zhao
2026-01-20 0:24 ` Nanzhe Zhao
2026-01-20 12:49 ` Chao Yu via Linux-f2fs-devel
2026-01-20 12:49 ` Chao Yu
2026-01-19 13:50 ` patchwork-bot+f2fs--- via Linux-f2fs-devel
2026-01-19 13:50 ` patchwork-bot+f2fs
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260112013320.8028-1-chao@kernel.org \
--to=linux-f2fs-devel@lists.sourceforge.net \
--cc=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.