[f2fs-dev] [PATCH RESEND] f2fs_io: add get_read_extents command for read extent cache ioctl

Yongpeng Yang <[email protected]>
Newsgroups net.sourceforge.lists.linux-f2fs-devel
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.