[f2fs-dev] [PATCH] f2fs_io: add extent_cache command to dump read extent cache
Yongpeng Yang <[email protected]> Sat, 15 Aug 2026 00:50:08 +0800
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Yongpeng Yang <[email protected]> Add an "extent_cache" subcommand that dumps the in-memory read extent cache of a given file to the kernel log, by passing the file's descriptor to the /sys/fs/f2fs/<dev>/extent_cache_debug sysfs entry introduced by the kernel counterpart patch. The dump itself is emitted by the kernel via f2fs_info(), inspect it with "dmesg | grep ino=<ino>". Signed-off-by: Yongpeng Yang <[email protected]> --- tools/f2fs_io/f2fs_io.c | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c index 06e0ea0..3025b7b 100644 --- a/tools/f2fs_io/f2fs_io.c +++ b/tools/f2fs_io/f2fs_io.c @@ -33,6 +33,7 @@ #include <sys/mman.h> #include <sys/sendfile.h> #include <sys/stat.h> +#include <sys/sysmacros.h> #include <sys/types.h> #include <termios.h> #include <time.h> @@ -1965,6 +1966,69 @@ static void do_precache_extents(int argc, char **argv, const struct cmd_desc *cm exit(0); } +#define extent_cache_desc "dump the in-memory read extent cache of a file" +#define extent_cache_help \ +"f2fs_io extent_cache [file_path]\n\n" \ +"Dump the in-memory read extent cache (largest extent plus every rbtree\n" \ +"node, as fofs/blk/len) of the given file to the kernel log by passing\n" \ +"its file descriptor to the per-sb sysfs entry\n" \ +"/sys/fs/f2fs/<dev>/extent_cache_debug.\n\n" \ +"Read the file beforehand so its extent tree is populated, then run\n" \ +"this command and inspect the dump with 'dmesg | grep ino=<ino>'.\n" + +static void do_extent_cache(int argc, char **argv, const struct cmd_desc *cmd) +{ + struct stat st; + char fd_str[32]; + char devlink[PATH_MAX]; + char devname[NAME_MAX + 1]; + char sysfs_path[PATH_MAX]; + char *base; + ssize_t rlen; + int fd, sfd, ret; + + if (argc != 2) { + fputs("Excess arguments\n\n", stderr); + fputs(cmd->cmd_help, stderr); + exit(1); + } + + /* Open the target file; its fd is handed to the kernel. */ + fd = xopen(argv[1], O_RDONLY, 0); + if (fstat(fd, &st) < 0) + die_errno("fstat %s failed", argv[1]); + if (!S_ISREG(st.st_mode)) + die("%s is not a regular file", argv[1]); + + /* Resolve the kernel device name (sb->s_id) from st_dev. */ + ret = snprintf(devlink, sizeof(devlink), "/sys/dev/block/%u:%u", + major(st.st_dev), minor(st.st_dev)); + if (ret < 0 || (size_t)ret >= sizeof(devlink)) + die("device path too long"); + rlen = readlink(devlink, sysfs_path, sizeof(sysfs_path) - 1); + if (rlen < 0) + die_errno("readlink %s failed", devlink); + sysfs_path[rlen] = '\0'; + base = basename(sysfs_path); + snprintf(devname, sizeof(devname), "%s", base); + + ret = snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/fs/f2fs/%s/extent_cache_debug", devname); + if (ret < 0 || (size_t)ret >= sizeof(sysfs_path)) + die("sysfs path too long"); + + /* Pass the fd to the kernel; the dump is written to the kernel log. */ + snprintf(fd_str, sizeof(fd_str), "%d", fd); + sfd = xopen(sysfs_path, O_WRONLY, 0); + full_write(sfd, fd_str, strlen(fd_str)); + close(sfd); + + printf("ino=%lu extent cache dump written to kernel log\n" + "inspect with: dmesg | grep ino=%lu\n", st.st_ino, st.st_ino); + close(fd); + exit(0); +} + #define move_range_desc "moving a range of data blocks from source file to destination file" #define move_range_help \ "f2fs_io move_range [src_path] [dst_path] [src_start] [dst_start] " \ @@ -2636,6 +2700,7 @@ const struct cmd_desc cmd_list[] = { CMD(gc), CMD(checkpoint), CMD(precache_extents), + CMD(extent_cache), CMD(move_range), CMD(gc_range), CMD(listxattr), -- 2.43.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel