From: Yongpeng Yang <[email protected]> Add support for F2FS_IOC_GET_READ_CACHE_EXTENTS ioctl which exports the read extent cache of a file to userspace. Uses a two-call pattern: first queries node_count, then fetches all extents.
Signed-off-by: Yongpeng Yang <[email protected]> --- tools/f2fs_io/f2fs_io.c | 73 +++++++++++++++++++++++++++++++++++++++++ tools/f2fs_io/f2fs_io.h | 20 +++++++++++ 2 files changed, 93 insertions(+) diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c index 94e61b8..3084dda 100644 --- a/tools/f2fs_io/f2fs_io.c +++ b/tools/f2fs_io/f2fs_io.c @@ -1948,6 +1948,78 @@ static void do_precache_extents(int argc, char **argv, const struct cmd_desc *cm exit(0); } +#define get_read_extents_desc "get read extent cache entries" +#define get_read_extents_help \ +"f2fs_io get_read_extents [file_path]\n\n" \ +" file_path : path to the target file\n" + +static void do_get_read_extents(int argc, char **argv, + const struct cmd_desc *cmd) +{ + struct f2fs_read_cache_extent *rec; + unsigned int i, count; + size_t alloc_size; + int fd, ret; + + if (argc != 2) { + fputs("Excess arguments\n\n", stderr); + fputs(cmd->cmd_help, stderr); + exit(1); + } + + fd = xopen(argv[1], O_RDONLY, 0); + + /* first call: ext_count=0 to query the actual count */ + alloc_size = sizeof(struct f2fs_read_cache_extent); + rec = xmalloc(alloc_size); + memset(rec, 0, alloc_size); + + ret = ioctl(fd, F2FS_IOC_GET_READ_CACHE_EXTENTS, rec); + if (ret < 0) + die_errno("F2FS_IOC_GET_READ_CACHE_EXTENTS (query) failed"); + + count = rec->node_count; + printf("flags: 0x%x", rec->flags); + if (rec->flags & F2FS_EXT_FL_NO_EXTENT) + printf(" (NO_EXTENT: extent cache disabled)"); + printf("\n"); + printf("largest extent: fofs=%u blk=%u len=%u access_mode=%u\n", + rec->largest.fofs, rec->largest.blk, rec->largest.len, + rec->largest.last_access_mode); + printf("extent node count: %u\n", count); + + if ((rec->flags & F2FS_EXT_FL_NO_EXTENT) || count == 0) { + free(rec); + close(fd); + exit(0); + } + free(rec); + + /* second call: allocate array and fetch all extents */ + alloc_size = sizeof(struct f2fs_read_cache_extent) + + count * sizeof(struct f2fs_cache_extent_info); + rec = xmalloc(alloc_size); + memset(rec, 0, alloc_size); + rec->ext_count = count; + + ret = ioctl(fd, F2FS_IOC_GET_READ_CACHE_EXTENTS, rec); + if (ret < 0) + die_errno("F2FS_IOC_GET_READ_CACHE_EXTENTS (fetch) failed"); + + printf("\t%-12s%-12s%-12s%-12s\n", "fofs", "blk", "len", "access_mode"); + for (i = 0; i < rec->ext_count && i < count; i++) { + printf("%u\t%-12u%-12u%-12u%-12u\n", i, + rec->extents[i].fofs, + rec->extents[i].blk, + rec->extents[i].len, + rec->extents[i].last_access_mode); + } + + free(rec); + 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] " \ @@ -2650,6 +2722,7 @@ const struct cmd_desc cmd_list[] = { CMD(gc), CMD(checkpoint), CMD(precache_extents), + CMD(get_read_extents), CMD(move_range), CMD(gc_range), CMD(listxattr), diff --git a/tools/f2fs_io/f2fs_io.h b/tools/f2fs_io/f2fs_io.h index 539964f..a84a299 100644 --- a/tools/f2fs_io/f2fs_io.h +++ b/tools/f2fs_io/f2fs_io.h @@ -96,6 +96,8 @@ typedef u32 __be32; #define F2FS_IOC_START_ATOMIC_REPLACE _IO(F2FS_IOCTL_MAGIC, 25) #define F2FS_IOC_GET_DEV_ALIAS_FILE _IOR(F2FS_IOCTL_MAGIC, 26, __u32) #define F2FS_IOC_IO_PRIO _IOW(F2FS_IOCTL_MAGIC, 27, __u32) +#define F2FS_IOC_GET_READ_CACHE_EXTENTS _IOWR(F2FS_IOCTL_MAGIC, 28, \ + struct f2fs_read_cache_extent) #ifndef FSCRYPT_POLICY_V1 #define FSCRYPT_POLICY_V1 0 @@ -263,3 +265,21 @@ struct f2fs_comp_option { u8 algorithm; u8 log_cluster_size; }; + +struct f2fs_cache_extent_info { + u32 fofs; /* start file offset in blocks */ + u32 blk; /* start block address */ + u32 len; /* length in blocks */ + u32 last_access_mode; /* last access mode of extent_node */ +}; + +#define F2FS_EXT_FL_NO_EXTENT 0x1 + +struct f2fs_read_cache_extent { + u32 ext_count; /* in: array capacity; out: mapped extent count */ + u32 flags; /* out: status flags */ + u32 node_count; /* out: total extent nodes in tree */ + u32 reserved; + struct f2fs_cache_extent_info largest; /* out: largest extent */ + struct f2fs_cache_extent_info extents[]; /* out: extent array */ +}; -- 2.43.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
