diff mbox series

[f2fs-dev,v2,1/2] f2fs_io: add [get|set_attr] to access inode extra attributes

Message ID 20230604035623.58572-1-shengyong@oppo.com (mailing list archive)
State New
Headers show
Series [f2fs-dev,v2,1/2] f2fs_io: add [get|set_attr] to access inode extra attributes | expand

Commit Message

Sheng Yong June 4, 2023, 3:56 a.m. UTC
This patch adds get_attr and set_attr to access inode's extra
attributes.

Signed-off-by: Sheng Yong <shengyong@oppo.com>
---
v2: update manpage of f2fs_io

---
 man/f2fs_io.8           |  65 ++++++++++++++++
 tools/f2fs_io/f2fs_io.c | 165 ++++++++++++++++++++++++++++++++++++++++
 tools/f2fs_io/f2fs_io.h |  34 +++++++++
 3 files changed, 264 insertions(+)
diff mbox series

Patch

diff --git a/man/f2fs_io.8 b/man/f2fs_io.8
index 33789c2..591599f 100644
--- a/man/f2fs_io.8
+++ b/man/f2fs_io.8
@@ -135,6 +135,71 @@  Reserve free blocks to prepare decompressing blocks in the file.
 .TP
 \fBgc\fR \fI[sync_mode] [file]\fR
 Trigger filesystem GC
+.TP
+\fBget_attr\fR \fI[field] [file]\fR
+Get value of an extra attribution from a f2fs inode. The
+.I field
+parameter can be:
+.RS 1.2in
+.TP
+.B total_size
+total size of extra attribution area
+.TP
+.B isize
+size of extra attribution area of the f2fs inode
+.TP
+.B inline_xattr_size
+size of inline xattr size
+.TP
+.B projid
+project quota ID
+.TP
+.B inode_chksum
+inode checksum
+.TP
+.B crtime
+inode create time
+.TP
+.B cblocks
+number of compressed blocks
+.TP
+.B coption
+options of compression
+.RE
+.TP
+\fBset_attr\fR \fI[field] [values] [file]\fR
+Set value of a writable extra attribution to a f2fs inode. The
+.I field
+and
+.I values
+can be:
+.RS 1.2in
+.TP
+.B inline_xattr_size
+.I values
+is \fI[size]\fR
+.TP
+.B coption
+.I values
+are \fI[algorithm] [log_cluster_size] [level] [flag]\fR
+.TP
+.RS
+.TP
+.I
+algorithm
+compression algorithm (0:lz0, 1:lz4: 2:zstd, 3:lzorle)
+.TP
+.I log_cluster_size
+compression cluster log size (2 <= log_cluster_size <= 8)
+.TP
+.I level
+compression level
+.TP
+.I flag
+compression flag (1:chksum)
+.RE 1
+.RE 2
+.TP
 .SH AUTHOR
 This version of
 .B f2fs_io
diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index 5bc0baf..70e0347 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -1311,6 +1311,169 @@  static void do_gc(int argc, char **argv, const struct cmd_desc *cmd)
 	exit(0);
 }
 
+#define get_attr_desc "get inode extra attribute"
+#define get_attr_help "f2fs_io get_attr [field] [file_path]\n\n"	\
+"field can be\n"							\
+"  total_size\n"							\
+"  isize\n"								\
+"  inline_xattr_size\n"							\
+"  projid\n"								\
+"  inode_chksum\n"							\
+"  crtime\n"								\
+"  cblocks\n"								\
+"  coption\n"
+
+static const char *extra_attr_fields[] = {
+	[F2FS_EXTRA_ATTR_TOTAL_SIZE] = "total_size",
+	[F2FS_EXTRA_ATTR_ISIZE] = "isize",
+	[F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE] = "inline_xattr_size",
+	[F2FS_EXTRA_ATTR_PROJID] = "projid",
+	[F2FS_EXTRA_ATTR_INODE_CHKSUM] = "inode_chksum",
+	[F2FS_EXTRA_ATTR_CRTIME] = "crtime",
+	[F2FS_EXTRA_ATTR_COMPR_BLOCKS] = "cblocks",
+	[F2FS_EXTRA_ATTR_COMPR_OPTION] = "coption",
+};
+
+static void do_get_attr(int argc, char **argv, const struct cmd_desc *cmd)
+{
+	struct f2fs_extra_attr attr = {0};
+	struct timespec ts = {0};
+	struct f2fs_comp_option_v2 coption = {0};
+	int ret, fd;
+
+	if (argc != 3) {
+		fputs("Excess arguments\n\n", stderr);
+		fputs(cmd->cmd_help, stderr);
+		exit(1);
+	}
+
+	for (attr.field = 0; attr.field < F2FS_EXTRA_ATTR_MAX; attr.field++) {
+		if (!strcmp(extra_attr_fields[attr.field], argv[1]))
+			break;
+	}
+
+	switch (attr.field) {
+	case F2FS_EXTRA_ATTR_TOTAL_SIZE:
+	case F2FS_EXTRA_ATTR_ISIZE:
+	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
+	case F2FS_EXTRA_ATTR_PROJID:
+	case F2FS_EXTRA_ATTR_INODE_CHKSUM:
+	case F2FS_EXTRA_ATTR_COMPR_BLOCKS:
+		attr.attr_size = sizeof(attr.attr);
+		break;
+	case F2FS_EXTRA_ATTR_CRTIME:
+		attr.attr_size = sizeof(ts);
+		attr.attr = (unsigned long)&ts;
+		break;
+	case F2FS_EXTRA_ATTR_COMPR_OPTION:
+		attr.attr_size = sizeof(coption);
+		attr.attr = (unsigned long)&coption;
+		break;
+	default:
+		die("Unknown field");
+	}
+
+	fd = xopen(argv[2], O_RDONLY, 0);
+
+	ret = ioctl(fd, F2FS_IOC_GET_EXTRA_ATTR, &attr);
+	if (ret < 0)
+		die_errno("F2FS_IOC_GET_EXTRA_ATTR failed");
+
+	switch (attr.field) {
+	case F2FS_EXTRA_ATTR_TOTAL_SIZE:
+	case F2FS_EXTRA_ATTR_ISIZE:
+	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
+	case F2FS_EXTRA_ATTR_PROJID:
+	case F2FS_EXTRA_ATTR_COMPR_BLOCKS:
+		printf("%"PRIu64"\n", attr.attr);
+		break;
+	case F2FS_EXTRA_ATTR_INODE_CHKSUM:
+		printf("0x%"PRIx64"\n", attr.attr);
+		break;
+	case F2FS_EXTRA_ATTR_CRTIME:
+		printf("sec: %lu\nnsec: %lu\n", ts.tv_sec, ts.tv_nsec);
+		break;
+	case F2FS_EXTRA_ATTR_COMPR_OPTION:
+		printf("compression algorithm:%u\n", coption.algorithm);
+		printf("compression cluster log size:%u\n", coption.log_cluster_size);
+		printf("compression level:%u\n", coption.level);
+		printf("compression flag:0x%x\n", coption.flag);
+		break;
+	default:
+		die("Unknown field");
+	}
+
+	exit(0);
+}
+
+#define set_attr_desc "set inode extra attribute"
+#define set_attr_help "f2fs_io set_attr [field] [values] [file_path]\n\n"	\
+"field can be\n"								\
+"  inline_xattr_size : [values] is [size]\n"					\
+"  coption : [values] are [algorithm] [log_cluster_size] [level] [flag]\n"	\
+"    algorithm        : compression algorithm (0:lzo, 1: lz4, 2:zstd, 3:lzorle)\n"	\
+"    log_cluster_size : compression cluster log size (2 <= log_size <= 8)\n"	\
+"    level            : compression level\n"					\
+"    flag             : compression flag (1:chksum)\n"
+
+static void do_set_attr(int argc, char **argv, const struct cmd_desc *cmd)
+{
+	struct f2fs_extra_attr attr = {0};
+	struct f2fs_comp_option_v2 coption = {0};
+	int i;
+	int ret, fd;
+
+	if (argc < 4)
+		goto out;
+
+	if (!strcmp(argv[1], extra_attr_fields[F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE])) {
+		if (argc != 4)
+			goto out;
+		i = 2;
+		attr.field = F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE;
+		attr.attr_size = sizeof(attr.attr);
+		attr.attr = atoi(argv[i++]);
+	} else if (!strcmp(argv[1], extra_attr_fields[F2FS_EXTRA_ATTR_COMPR_OPTION])) {
+		if (argc != 7)
+			goto out;
+		i = 2;
+		coption.algorithm = atoi(argv[i++]);
+		coption.log_cluster_size = atoi(argv[i++]);
+		coption.level = atoi(argv[i++]);
+		coption.flag = atoi(argv[i++]);
+		attr.field = F2FS_EXTRA_ATTR_COMPR_OPTION;
+		attr.attr_size = sizeof(coption);
+		attr.attr = (unsigned long)&coption;
+	} else {
+		die("Unknown or read only field");
+	}
+
+	fd = xopen(argv[i], O_WRONLY, 0);
+
+	ret = ioctl(fd, F2FS_IOC_SET_EXTRA_ATTR, &attr);
+	if (ret < 0)
+		die_errno("F2FS_IOC_SET_EXTRA_ATTR failed");
+
+	switch (attr.field) {
+	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
+		printf("set inline_xattr_size:%"PRIu64"\n", attr.attr);
+		break;
+	case F2FS_EXTRA_ATTR_COMPR_OPTION:
+		printf("set compression option: algorithm=%u, "
+			"log_cluster_size=%u, level=%u, flag=0x%x\n",
+			coption.algorithm, coption.log_cluster_size,
+			coption.level, coption.flag);
+		break;
+	}
+
+	exit(0);
+out:
+	fputs("Excess arguments\n\n", stderr);
+	fputs(cmd->cmd_help, stderr);
+	exit(1);
+}
+
+
 #define CMD_HIDDEN 	0x0001
 #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
 #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
@@ -1343,6 +1506,8 @@  const struct cmd_desc cmd_list[] = {
 	CMD(get_filename_encrypt_mode),
 	CMD(rename),
 	CMD(gc),
+	CMD(get_attr),
+	CMD(set_attr),
 	{ NULL, NULL, NULL, NULL, 0 }
 };
 
diff --git a/tools/f2fs_io/f2fs_io.h b/tools/f2fs_io/f2fs_io.h
index 58be8f8..2c181e5 100644
--- a/tools/f2fs_io/f2fs_io.h
+++ b/tools/f2fs_io/f2fs_io.h
@@ -91,6 +91,10 @@  typedef u32	__be32;
 #define F2FS_IOC_DECOMPRESS_FILE        _IO(F2FS_IOCTL_MAGIC, 23)
 #define F2FS_IOC_COMPRESS_FILE          _IO(F2FS_IOCTL_MAGIC, 24)
 #define F2FS_IOC_START_ATOMIC_REPLACE	_IO(F2FS_IOCTL_MAGIC, 25)
+#define F2FS_IOC_GET_EXTRA_ATTR		_IOR(F2FS_IOCTL_MAGIC, 26,	\
+						struct f2fs_extra_attr)
+#define F2FS_IOC_SET_EXTRA_ATTR		_IOW(F2FS_IOCTL_MAGIC, 27,	\
+						struct f2fs_extra_attr)
 
 #ifndef FSCRYPT_POLICY_V1
 #define FSCRYPT_POLICY_V1		0
@@ -216,3 +220,33 @@  struct f2fs_comp_option {
 	u8 algorithm;
 	u8 log_cluster_size;
 };
+
+struct f2fs_comp_option_v2 {
+	u8 algorithm;
+	u8 log_cluster_size;
+	u8 level;
+	u8 flag;
+};
+
+enum {
+	F2FS_EXTRA_ATTR_TOTAL_SIZE,		/* ro, size of extra attr area */
+	F2FS_EXTRA_ATTR_ISIZE,			/* ro, i_extra_isize */
+	F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE,	/* rw, i_inline_xattr_size */
+	F2FS_EXTRA_ATTR_PROJID,			/* ro, i_projid */
+	F2FS_EXTRA_ATTR_INODE_CHKSUM,		/* ro, i_inode_chksum */
+	F2FS_EXTRA_ATTR_CRTIME,			/* ro, i_crtime, i_crtime_nsec */
+	F2FS_EXTRA_ATTR_COMPR_BLOCKS,		/* ro, i_compr_blocks */
+	F2FS_EXTRA_ATTR_COMPR_OPTION,		/* rw, i_compress_algorithm,
+						 * i_log_cluster_size,
+						 * i_compress_flag
+						 */
+	F2FS_EXTRA_ATTR_MAX,
+};
+
+struct f2fs_extra_attr {
+	u8 field;	/* F2FS_EXTRA_ATTR_* */
+	u8 rsvd1;
+	u16 attr_size;	/* size of @attr */
+	u32 rsvd2;
+	u64 attr;	/* attr value or pointer */
+};