[f2fs-dev] [PATCH 3/3] f2fs: dump read extent cache via sysfs for debugging

Yongpeng Yang <[email protected]> Sat, 15 Aug 2026 00:49:28 +0800
Newsgroups net.sourceforge.lists.linux-f2fs-devel
Message-ID <[email protected]>
From: Yongpeng Yang <[email protected]>

Add a write-only per-sb sysfs entry "extent_cache_debug": writing a file
descriptor resolves the inode in the writer's context, dumps the largest
extent and every rbtree node (fofs/blk/len) to the kernel log via
f2fs_info(). A matching f2fs_io "extent_cache" subcommand is added in
f2fs-tools.

Signed-off-by: Yongpeng Yang <[email protected]>
---
 fs/f2fs/extent_cache.c | 45 ++++++++++++++++++++++++++++++++++++++++++
 fs/f2fs/f2fs.h         |  1 +
 fs/f2fs/sysfs.c        | 18 +++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index aaad72fa1553..d5d57bc642c8 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/f2fs_fs.h>
 
 #include "f2fs.h"
@@ -1268,6 +1269,50 @@ static void __init_extent_tree_info(struct extent_tree_info *eti)
 	atomic_set(&eti->total_ext_node, 0);
 }
 
+/* Dump the read extent cache of the inode behind @fd to the kernel log. */
+int f2fs_dump_read_extent_cache(struct f2fs_sb_info *sbi, int fd)
+{
+	struct fd f = fdget(fd);
+	struct inode *inode;
+	struct extent_tree *et;
+	struct rb_node *node;
+	struct extent_node *en;
+	unsigned int count = 0;
+	int ret = 0;
+
+	if (fd_empty(f))
+		return -EBADF;
+
+	inode = file_inode(fd_file(f));
+	if (inode->i_sb != sbi->sb) {
+		fdput(f);
+		return -EINVAL;
+	}
+
+	et = F2FS_I(inode)->extent_tree[EX_READ];
+	if (!et) {
+		f2fs_info(sbi, "ino=%llu: read extent cache disabled",
+			  (unsigned long long)inode->i_ino);
+		goto out;
+	}
+
+	read_lock(&et->lock);
+	f2fs_info(sbi, "ino=%llu largest: fofs=%u blk=%u len=%u node_count=%u",
+		  (unsigned long long)inode->i_ino, et->largest.fofs,
+		  et->largest.blk, et->largest.len,
+		  atomic_read(&et->node_cnt));
+	for (node = rb_first_cached(&et->root); node; node = rb_next(node)) {
+		en = rb_entry(node, struct extent_node, rb_node);
+		f2fs_info(sbi, "  [%u] fofs=%u blk=%u len=%u",
+			  count, en->ei.fofs, en->ei.blk, en->ei.len);
+		count++;
+	}
+	read_unlock(&et->lock);
+out:
+	fdput(f);
+	return ret;
+}
+
 void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi)
 {
 	__init_extent_tree_info(&sbi->extent_tree[EX_READ]);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1b96d8718c5c..be2bd6e2a2bd 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -4648,6 +4648,7 @@ void f2fs_update_read_extent_cache_range(struct dnode_of_data *dn,
 			pgoff_t fofs, block_t blkaddr, unsigned int len);
 unsigned int f2fs_shrink_read_extent_tree(struct f2fs_sb_info *sbi,
 			int nr_shrink);
+int f2fs_dump_read_extent_cache(struct f2fs_sb_info *sbi, int fd);
 
 /* block age extent cache ops */
 void f2fs_init_age_extent_tree(struct inode *inode);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 3201e2185fea..046d68962d18 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1368,6 +1368,23 @@ F2FS_GENERAL_RO_ATTR(avg_vblocks);
 F2FS_GENERAL_RO_ATTR(defrag_blocks);
 #endif
 
+static ssize_t extent_cache_debug_store(struct f2fs_attr *a,
+		struct f2fs_sb_info *sbi, const char *buf, size_t count)
+{
+	int fd, ret;
+
+	ret = kstrtoint(buf, 0, &fd);
+	if (ret < 0)
+		return ret;
+	ret = f2fs_dump_read_extent_cache(sbi, fd);
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+static struct f2fs_attr f2fs_attr_extent_cache_debug = __ATTR(
+		extent_cache_debug, 0200, NULL, extent_cache_debug_store);
+
 #ifdef CONFIG_FS_ENCRYPTION
 F2FS_FEATURE_RO_ATTR(encryption);
 F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2);
@@ -1491,6 +1508,7 @@ static struct attribute *f2fs_attrs[] = {
 	ATTR_LIST(avg_vblocks),
 	ATTR_LIST(defrag_blocks),
 #endif
+	ATTR_LIST(extent_cache_debug),
 #ifdef CONFIG_BLK_DEV_ZONED
 	ATTR_LIST(unusable_blocks_per_sec),
 	ATTR_LIST(max_open_zones),
-- 
2.43.0



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel