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

Reply via email to