All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr
@ 2017-11-02  3:56 Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 1/9] fsck.f2fs: do not set fix_on directly Sheng Yong
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

v1-v2:
[PATCH 3] print values of USER/SECRUITY xattr as hex instead of plain text.
[PATCH 4] replace xattr value if it already exists by setting parameter
          `flags' as 0 of fsetxattr.
[PATCH 1/7] move message printing modification into a different patch.

thanks,
Sheng

Sheng Yong (9):
  fsck.f2fs: do not set fix_on directly
  fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap
  dump/fsck: introduce print_xattr_entry
  dump.f2fs: introduce dump_xattr
  dump.f2fs: do not dump encrypted files
  fsck.f2fs: introduce new option --dry-run
  fsck.f2fs: introduce sanity_check_inode
  f2fs-tools: remove unused list.h
  fsck.f2fs: format output message of FIX_MSG

 fsck/dump.c       |  93 ++++++++++++++++++++++++++++------
 fsck/fsck.c       |  25 +++++++++-
 fsck/fsck.h       |   7 ++-
 fsck/main.c       |  16 +++++-
 fsck/mount.c      | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 fsck/xattr.c      |   2 +-
 fsck/xattr.h      |  54 +++++++++++++++++++-
 include/f2fs_fs.h |   1 +
 include/list.h    |  88 --------------------------------
 lib/libf2fs.c     |   1 +
 lib/libf2fs_io.c  |   3 ++
 11 files changed, 313 insertions(+), 123 deletions(-)
 delete mode 100644 include/list.h

-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 1/9] fsck.f2fs: do not set fix_on directly
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 2/9] fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap Sheng Yong
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

Do not set fix_on if it is allowed by user.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/main.c  | 2 +-
 fsck/mount.c | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index c9411eb..93037e1 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -429,7 +429,7 @@ static void do_fsck(struct f2fs_sb_info *sbi)
 				c.fix_on = 1;
 			break;
 		}
-	} else {
+	} else if (c.preen_mode) {
 		/*
 		 * we can hit this in 3 situations:
 		 *  1. fsck -f, fix_on has already been set to 1 when
diff --git a/fsck/mount.c b/fsck/mount.c
index 29af3b7..17da814 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -2031,7 +2031,6 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
 				 */
 				ASSERT_MSG("Invalid nat entry[0]: "
 					"blk_addr[0x%x]\n", ni.blk_addr);
-				c.fix_on = 1;
 				fsck->chk.valid_nat_entry_cnt--;
 			}
 
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 2/9] fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 1/9] fsck.f2fs: do not set fix_on directly Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry Sheng Yong
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

Fixing corrupted data depends on c.fix_on. If it's not set, we should not
force fixing corrupted data.  So if nat entries are found invalid when
building nat_area_bitmap, we should just set c.bug_on, and fix it later.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/mount.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 17da814..d8bc50c 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1877,8 +1877,14 @@ void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
 	ret = dev_read_block(nat_block, block_addr);
 	ASSERT(ret >= 0);
 
-	memset(&nat_block->entries[entry_off], 0,
+	if (nid == F2FS_NODE_INO(sbi) || nid == F2FS_META_INO(sbi)) {
+		FIX_MSG("nid [0x%x] block_addr= 0x%x -> 0x1", nid,
+			le32_to_cpu(nat_block->entries[entry_off].block_addr));
+		nat_block->entries[entry_off].block_addr = cpu_to_le32(0x1);
+	} else {
+		memset(&nat_block->entries[entry_off], 0,
 					sizeof(struct f2fs_nat_entry));
+	}
 
 	ret = dev_write_block(nat_block, block_addr);
 	ASSERT(ret >= 0);
@@ -2000,13 +2006,14 @@ void build_nat_area_bitmap(struct f2fs_sb_info *sbi)
 
 			if ((nid + i) == F2FS_NODE_INO(sbi) ||
 					(nid + i) == F2FS_META_INO(sbi)) {
-				/* block_addr of node/meta inode should be 0x1 */
+				/*
+				 * block_addr of node/meta inode should be 0x1.
+				 * Set this bit, and fsck_verify will fix it.
+				 */
 				if (le32_to_cpu(nat_block->entries[i].block_addr) != 0x1) {
-					FIX_MSG("ino: 0x%x node/meta inode, block_addr= 0x%x -> 0x1",
+					ASSERT_MSG("\tError: ino[0x%x] block_addr[0x%x] is invalid\n",
 							nid + i, le32_to_cpu(nat_block->entries[i].block_addr));
-					nat_block->entries[i].block_addr = cpu_to_le32(0x1);
-					ret = dev_write_block(nat_block, block_addr);
-					ASSERT(ret >= 0);
+					f2fs_set_bit(nid + i, fsck->nat_area_bitmap);
 				}
 				continue;
 			}
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 1/9] fsck.f2fs: do not set fix_on directly Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 2/9] fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-03  3:27   ` Jaegeuk Kim
  2017-11-02  3:56 ` [RFC PATCH v2 4/9] dump.f2fs: introduce dump_xattr Sheng Yong
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
and introduces print_xattr_entry which tries to parse an xattr entry
accroding to its xattr index.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/dump.c  |  18 ++++-----
 fsck/fsck.h  |   7 +++-
 fsck/mount.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 fsck/xattr.c |   2 +-
 fsck/xattr.h |  54 +++++++++++++++++++++++++-
 5 files changed, 188 insertions(+), 16 deletions(-)

diff --git a/fsck/dump.c b/fsck/dump.c
index 128dc53..90fd073 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
 	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
 			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
 			ni.ino == ni.nid) {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
 		dump_file(sbi, &ni, node_blk, force);
 	} else {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
 		MSG(force, "Invalid (i)node block\n\n");
 	}
 
 	free(node_blk);
 }
 
-static void dump_node_from_blkaddr(u32 blk_addr)
+static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 {
 	struct f2fs_node *node_blk;
 	int ret;
@@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
 	ASSERT(ret >= 0);
 
 	if (c.dbg_lv > 0)
-		print_node_info(node_blk, 0);
+		print_node_info(sbi, node_blk, 0);
 	else
-		print_inode_info(&node_blk->i, 1);
+		print_inode_info(sbi, node_blk, 1);
 
 	free(node_blk);
 }
@@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 
 	/* print inode */
 	if (c.dbg_lv > 0)
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 
 	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
 		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
@@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 					nid, ni.blk_addr);
 		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 		dump_data_offset(ni.blk_addr,
 			le16_to_cpu(sum_entry.ofs_in_node));
 	} else {
@@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 		if (ni.ino == ni.nid) {
 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 		} else {
 			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
 					nid, ni.blk_addr);
 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 			dump_node_offset(ni.blk_addr);
 		}
 	}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1e8ed0b..f8caa46 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);
 
 extern void update_free_segments(struct f2fs_sb_info *);
 void print_cp_state(u32);
-extern void print_node_info(struct f2fs_node *, int);
-extern void print_inode_info(struct f2fs_inode *, int);
+extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
+extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
 extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
 extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
 				unsigned int, int *);
@@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
 int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
 int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
 
+/* xattr.c */
+void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
+
 #endif /* _FSCK_H_ */
diff --git a/fsck/mount.c b/fsck/mount.c
index d8bc50c..d631547 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -9,7 +9,9 @@
  * published by the Free Software Foundation.
  */
 #include "fsck.h"
+#include "xattr.h"
 #include <locale.h>
+#include <linux/posix_acl.h>
 
 u32 get_free_segments(struct f2fs_sb_info *sbi)
 {
@@ -35,8 +37,116 @@ void update_free_segments(struct f2fs_sb_info *sbi)
 	i++;
 }
 
-void print_inode_info(struct f2fs_inode *inode, int name)
+void print_acl(char *value, int size)
 {
+	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+	const char *end = value + size;
+	int i, count;
+
+	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
+		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
+				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
+		return;
+	}
+
+	count = f2fs_acl_count(size);
+	if (count <= 0) {
+		MSG(0, "Invalid ACL value size %d\n", size);
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		if ((char *)entry > end) {
+			MSG(0, "Invalid ACL entries count %d\n", count);
+			return;
+		}
+
+		switch (le16_to_cpu(entry->e_tag)) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			MSG(0, "tag:0x%x perm:0x%x\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+		case ACL_USER:
+			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		default:
+			MSG(0, "Unknown ACL tag 0x%x\n",
+					le16_to_cpu(entry->e_tag));
+			return;
+		}
+	}
+}
+
+void print_xattr_entry(struct f2fs_xattr_entry *ent)
+{
+	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
+	struct fscrypt_context *ctx;
+	int i;
+
+	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
+	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
+		MSG(0, "%c", ent->e_name[i]);
+	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
+			ent->e_name_len, le16_to_cpu(ent->e_value_size));
+
+	switch (ent->e_name_index) {
+	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
+	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
+		print_acl(value, le16_to_cpu(ent->e_value_size));
+		break;
+	case F2FS_XATTR_INDEX_USER:
+	case F2FS_XATTR_INDEX_SECURITY:
+	case F2FS_XATTR_INDEX_TRUSTED:
+	case F2FS_XATTR_INDEX_LUSTRE:
+		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
+			MSG(0, "%02X", value[i]);
+		MSG(0, "\n");
+		break;
+	case F2FS_XATTR_INDEX_ENCRYPTION:
+		ctx = (struct fscrypt_context *)value;
+		MSG(0, "format: %d\n", ctx->format);
+		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
+		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
+		MSG(0, "flags: 0x%x\n", ctx->flags);
+		MSG(0, "master_key_descriptor: ");
+		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
+			MSG(0, "%02X", ctx->master_key_descriptor[i]);
+		MSG(0, "\nnonce: ");
+		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
+			MSG(0, "%02X", ctx->nonce[i]);
+		MSG(0, "\n");
+		break;
+	default:
+		break;
+	}
+}
+
+void print_inode_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node, int name)
+{
+	struct f2fs_inode *inode = &node->i;
+	void *xattr_addr;
+	struct f2fs_xattr_entry *ent;
 	unsigned char en[F2FS_NAME_LEN + 1];
 	unsigned int i = 0;
 	int namelen = le32_to_cpu(inode->i_namelen);
@@ -111,17 +221,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
 	DISP_u32(inode, i_nid[3]);	/* indirect */
 	DISP_u32(inode, i_nid[4]);	/* double indirect */
 
+	xattr_addr = read_all_xattrs(sbi, node);
+	list_for_each_xattr(ent, xattr_addr) {
+		print_xattr_entry(ent);
+	}
+	free(xattr_addr);
+
 	printf("\n");
 }
 
-void print_node_info(struct f2fs_node *node_block, int verbose)
+void print_node_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node_block, int verbose)
 {
 	nid_t ino = le32_to_cpu(node_block->footer.ino);
 	nid_t nid = le32_to_cpu(node_block->footer.nid);
 	/* Is this inode? */
 	if (ino == nid) {
 		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
-		print_inode_info(&node_block->i, verbose);
+		print_inode_info(sbi, node_block, verbose);
 	} else {
 		int i;
 		u32 *dump_blk = (u32 *)node_block;
diff --git a/fsck/xattr.c b/fsck/xattr.c
index 3f5c7d3..1d0f7d3 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -20,7 +20,7 @@
 #define XATTR_CREATE 0x1
 #define XATTR_REPLACE 0x2
 
-static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
+void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
 {
 	struct f2fs_xattr_header *header;
 	void *txattr_addr;
diff --git a/fsck/xattr.h b/fsck/xattr.h
index b414629..beed3bb 100644
--- a/fsck/xattr.h
+++ b/fsck/xattr.h
@@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
 	char e_name[0];		/* attribute name */
 };
 
+#define FS_KEY_DESCRIPTOR_SIZE 8
+#define FS_KEY_DERIVATION_NONCE_SIZE 16
+
+struct fscrypt_context {
+	u8 format;
+	u8 contents_encryption_mode;
+	u8 filenames_encryption_mode;
+	u8 flags;
+	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+} __attribute__((packed));
+
+#define F2FS_ACL_VERSION	0x0001
+
+struct f2fs_acl_entry {
+	__le16 e_tag;
+	__le16 e_perm;
+	__le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+	__le16 e_tag;
+	__le16 e_perm;
+};
+
+struct f2fs_acl_header {
+	__le32 a_version;
+};
+
+static inline int f2fs_acl_count(int size)
+{
+	ssize_t s;
+	size -= sizeof(struct f2fs_acl_header);
+	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct f2fs_acl_entry_short))
+			return -1;
+		return size / sizeof(struct f2fs_acl_entry_short);
+	} else {
+		if (s % sizeof(struct f2fs_acl_entry))
+			return -1;
+		return s / sizeof(struct f2fs_acl_entry) + 4;
+	}
+}
+
 #define XATTR_ROUND	(3)
 
 #define XATTR_SELINUX_SUFFIX "selinux"
-#define F2FS_XATTR_INDEX_SECURITY	6
+#define F2FS_XATTR_INDEX_USER			1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define F2FS_XATTR_INDEX_TRUSTED		4
+#define F2FS_XATTR_INDEX_LUSTRE			5
+#define F2FS_XATTR_INDEX_SECURITY		6
+#define F2FS_XATTR_INDEX_ENCRYPTION		9
+
 #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
 
 #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 4/9] dump.f2fs: introduce dump_xattr
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (2 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 5/9] dump.f2fs: do not dump encrypted files Sheng Yong
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

This patch introduces dump_xattr to create xattrs for dumped files.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/dump.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 3 deletions(-)

diff --git a/fsck/dump.c b/fsck/dump.c
index 90fd073..3d64cb7 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -11,6 +11,9 @@
 #include <inttypes.h>
 
 #include "fsck.h"
+#include "xattr.h"
+#include <attr/xattr.h>
+#include <linux/xattr.h>
 #include <locale.h>
 
 #define BUF_SZ	80
@@ -310,15 +313,67 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
 	free(node_blk);
 }
 
+static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
+{
+	void *xattr;
+	struct f2fs_xattr_entry *ent;
+	char xattr_name[F2FS_NAME_LEN] = {0};
+	int ret;
+
+	xattr = read_all_xattrs(sbi, node_blk);
+
+	list_for_each_xattr(ent, xattr) {
+		char *name = strndup(ent->e_name, ent->e_name_len);
+		void *value = ent->e_name + ent->e_name_len;
+
+		if (!name)
+			continue;
+
+		switch (ent->e_name_index) {
+		case F2FS_XATTR_INDEX_USER:
+			ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
+				       XATTR_USER_PREFIX, name);
+			break;
+
+		case F2FS_XATTR_INDEX_SECURITY:
+			ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
+				       XATTR_SECURITY_PREFIX, name);
+			break;
+		case F2FS_XATTR_INDEX_TRUSTED:
+			ret = snprintf(xattr_name, F2FS_NAME_LEN, "%s%s",
+				       XATTR_TRUSTED_PREFIX, name);
+			break;
+		default:
+			MSG(0, "Unknown xattr index 0x%x\n", ent->e_name_index);
+			free(name);
+			continue;
+		}
+		if (ret >= F2FS_NAME_LEN) {
+			MSG(0, "XATTR index 0x%x name too long\n", ent->e_name_index);
+			free(name);
+			continue;
+		}
+
+		DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name);
+		ret = fsetxattr(c.dump_fd, xattr_name, value,
+				le16_to_cpu(ent->e_value_size), 0);
+		if (ret)
+			MSG(0, "XATTR index 0x%x set xattr failed error %d\n",
+			    ent->e_name_index, errno);
+
+		free(name);
+	}
+
+	free(xattr);
+}
+
 static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 					struct f2fs_node *node_blk)
 {
 	u32 i = 0;
 	u64 ofs = 0;
 
-	/* TODO: need to dump xattr */
-
-	if((node_blk->i.i_inline & F2FS_INLINE_DATA)){
+	if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
 		DBG(3, "ino[0x%x] has inline data!\n", nid);
 		/* recover from inline data */
 		dev_write_dump(((unsigned char *)node_blk) + INLINE_DATA_OFFSET,
@@ -345,6 +400,8 @@ static void dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 		else
 			ASSERT(0);
 	}
+
+	dump_xattr(sbi, node_blk);
 }
 
 static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 5/9] dump.f2fs: do not dump encrypted files
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (3 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 4/9] dump.f2fs: introduce dump_xattr Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 6/9] fsck.f2fs: introduce new option --dry-run Sheng Yong
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

If a file is encrypted, its content is cipher text on the storage. So
there is no need to dump an encrypted file.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/dump.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/fsck/dump.c b/fsck/dump.c
index 3d64cb7..27736ae 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -410,12 +410,17 @@ static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
 	struct f2fs_inode *inode = &node_blk->i;
 	u32 imode = le32_to_cpu(inode->i_mode);
 	u32 namelen = le32_to_cpu(inode->i_namelen);
-	unsigned char name[F2FS_NAME_LEN + 1] = {0};
+	char name[F2FS_NAME_LEN + 1] = {0};
 	char path[1024] = {0};
 	char ans[255] = {0};
-	int enc_name = file_enc_name(inode);
+	int is_encrypted = file_is_encrypt(inode);
 	int ret;
 
+	if (is_encrypted) {
+		MSG(force, "File is encrypted\n");
+		return;
+	}
+
 	if (!S_ISREG(imode) || namelen == 0 || namelen > F2FS_NAME_LEN) {
 		MSG(force, "Not a regular file or wrong name info\n\n");
 		return;
@@ -433,8 +438,7 @@ dump:
 		ASSERT(ret >= 0);
 
 		/* make a file */
-		namelen = convert_encrypted_name(inode->i_name, namelen,
-							name, enc_name);
+		strncpy(name, (const char *)inode->i_name, namelen);
 		name[namelen] = 0;
 		sprintf(path, "./lost_found/%s", name);
 
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 6/9] fsck.f2fs: introduce new option --dry-run
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (4 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 5/9] dump.f2fs: do not dump encrypted files Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 7/9] fsck.f2fs: introduce sanity_check_inode Sheng Yong
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

With --dry-run enabled, fsck.f2fs will do all checks and "fixes" except
that all fixes will not be written to storage at last.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/main.c       | 14 +++++++++++++-
 include/f2fs_fs.h |  1 +
 lib/libf2fs.c     |  1 +
 lib/libf2fs_io.c  |  3 +++
 4 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/fsck/main.c b/fsck/main.c
index 93037e1..baa8efc 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -18,6 +18,7 @@
 #include "fsck.h"
 #include <libgen.h>
 #include <ctype.h>
+#include <getopt.h>
 
 struct f2fs_fsck gfsck;
 
@@ -30,6 +31,7 @@ void fsck_usage()
 	MSG(0, "  -f check/fix entire partition\n");
 	MSG(0, "  -p preen mode [default:0 the same as -a [0|1]]\n");
 	MSG(0, "  -t show directory tree\n");
+	MSG(0, "  --dry-run do not really fix corruptions\n");
 	exit(1);
 }
 
@@ -117,10 +119,20 @@ void f2fs_parse_options(int argc, char *argv[])
 
 	if (!strcmp("fsck.f2fs", prog)) {
 		const char *option_string = ":ad:fp:t";
+		int opt = 0;
+		struct option long_opt[] = {
+			{"dry-run", no_argument, 0, 1},
+			{0, 0, 0, 0}
+		};
 
 		c.func = FSCK;
-		while ((option = getopt(argc, argv, option_string)) != EOF) {
+		while ((option = getopt_long(argc, argv, option_string,
+						long_opt, &opt)) != EOF) {
 			switch (option) {
+			case 1:
+				c.dry_run = 1;
+				MSG(0, "Info: Dry run\n");
+				break;
 			case 'a':
 				c.auto_fix = 1;
 				MSG(0, "Info: Fix the reported corruption.\n");
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index e1e299d..64a796d 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -300,6 +300,7 @@ struct f2fs_configuration {
 	int trimmed;
 	int func;
 	void *private;
+	int dry_run;
 	int fix_on;
 	int bug_on;
 	int auto_fix;
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 69f5ccc..259bd17 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -598,6 +598,7 @@ void f2fs_init_configuration(void)
 	c.trimmed = 0;
 	c.ro = 0;
 	c.kd = -1;
+	c.dry_run = 0;
 }
 
 static int is_mounted(const char *mpt, const char *device)
diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c
index 50ff171..8a79672 100644
--- a/lib/libf2fs_io.c
+++ b/lib/libf2fs_io.c
@@ -129,6 +129,9 @@ int dev_write(void *buf, __u64 offset, size_t len)
 {
 	int fd;
 
+	if (c.dry_run)
+		return 0;
+
 	if (c.sparse_mode)
 		return dev_write_sparse(buf, offset, len);
 
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 7/9] fsck.f2fs: introduce sanity_check_inode
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (5 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 6/9] fsck.f2fs: introduce new option --dry-run Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 8/9] f2fs-tools: remove unused list.h Sheng Yong
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

f2fs_iget checks if i_mode is valid. If it is not, the file cannot be
accessed as well as deleted. To make sure such files can be removed,
fsck adds the same check, and removes incorrect inode blocks.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/fsck.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 56a47be..77490d8 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -458,6 +458,25 @@ static int sanity_check_nid(struct f2fs_sb_info *sbi, u32 nid,
 	return 0;
 }
 
+static int sanity_check_inode(struct f2fs_sb_info *sbi, struct f2fs_node *node)
+{
+	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
+	struct f2fs_inode *fi = &node->i;
+
+	if (!(le16_to_cpu(fi->i_mode) & S_IFMT)) {
+		ASSERT_MSG("i_mode is not valid. [0x%x]", le16_to_cpu(fi->i_mode));
+		goto remove_node;
+	}
+
+	return 0;
+
+remove_node:
+	f2fs_set_bit(le32_to_cpu(node->footer.ino), fsck->nat_area_bitmap);
+	fsck->chk.valid_blk_cnt--;
+	fsck->chk.valid_node_cnt--;
+	return -EINVAL;
+}
+
 static int fsck_chk_xattr_blk(struct f2fs_sb_info *sbi, u32 ino,
 					u32 x_nid, u32 *blk_cnt)
 {
@@ -500,6 +519,8 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 		goto err;
 
 	if (ntype == TYPE_INODE) {
+		if (sanity_check_inode(sbi, node_blk))
+			goto err;
 		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni);
 	} else {
 		switch (ntype) {
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 8/9] f2fs-tools: remove unused list.h
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (6 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 7/9] fsck.f2fs: introduce sanity_check_inode Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02  3:56 ` [RFC PATCH v2 9/9] fsck.f2fs: format output message of FIX_MSG Sheng Yong
  2017-11-02 15:08 ` [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Chao Yu
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

Commit 7d96d138a378 ("fsck.f2fs: remove list.h") has already the usage
of list.h. So let's remove list.h itself.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
---
 include/list.h | 88 ----------------------------------------------------------
 1 file changed, 88 deletions(-)
 delete mode 100644 include/list.h

diff --git a/include/list.h b/include/list.h
deleted file mode 100644
index 571cd5c..0000000
--- a/include/list.h
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#define POISON_POINTER_DELTA 0
-#define LIST_POISON1  ((void *) (0x00100100 + POISON_POINTER_DELTA))
-#define LIST_POISON2  ((void *) (0x00200200 + POISON_POINTER_DELTA))
-
-#if !defined(offsetof)
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-#define container_of(ptr, type, member) ({                      \
-		const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-		(type *)( (char *)__mptr - offsetof(type,member) );})
-
-struct list_head {
-	struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-	struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
-	list->next = list;
-	list->prev = list;
-}
-
-static inline void __list_add(struct list_head *new,
-		struct list_head *prev,
-		struct list_head *next)
-{
-	next->prev = new;
-	new->next = next;
-	new->prev = prev;
-	prev->next = new;
-}
-
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head, head->next);
-}
-
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head->prev, head);
-}
-
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
-	next->prev = prev;
-	prev->next = next;
-}
-
-static inline void __list_del_entry(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-}
-
-static inline void list_del(struct list_head *entry)
-{
-	__list_del(entry->prev, entry->next);
-	entry->next = LIST_POISON1;
-	entry->prev = LIST_POISON2;
-}
-
-static inline int list_empty(const struct list_head *head)
-{
-	return head->next == head;
-}
-
-#define list_entry(ptr, type, member) \
-	container_of(ptr, type, member)
-
-#define list_for_each(pos, head) \
-	for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#define list_for_each_safe(pos, n, head) \
-	for (pos = (head)->next, n = pos->next; pos != (head); \
-			pos = n, n = pos->next)
-#define list_for_each_entry(pos, head, member)                          \
-	for (pos = list_entry((head)->next, typeof(*pos), member);      \
-			&pos->member != (head);    \
-			pos = list_entry(pos->member.next, typeof(*pos), member))
-#define list_for_each_entry_safe(pos, n, head, member)                  \
-	for (pos = list_entry((head)->next, typeof(*pos), member),      \
-			n = list_entry(pos->member.next, typeof(*pos), member); \
-			&pos->member != (head);                                    \
-			pos = n, n = list_entry(n->member.next, typeof(*n), member))
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH v2 9/9] fsck.f2fs: format output message of FIX_MSG
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (7 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 8/9] f2fs-tools: remove unused list.h Sheng Yong
@ 2017-11-02  3:56 ` Sheng Yong
  2017-11-02 15:08 ` [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Chao Yu
  9 siblings, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-02  3:56 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

This patch removes an extra '\n' at the end of the string in FIX_MSG.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
 fsck/fsck.c  | 4 ++--
 fsck/mount.c | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 77490d8..1905319 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -966,7 +966,7 @@ int fsck_chk_idnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 			else {
 				node_blk->in.nid[i] = 0;
 				need_fix = 1;
-				FIX_MSG("Set indirect node 0x%x -> 0\n", i);
+				FIX_MSG("Set indirect node 0x%x -> 0", i);
 			}
 skip:
 			child->pgofs += ADDRS_PER_BLOCK;
@@ -1006,7 +1006,7 @@ int fsck_chk_didnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 			else {
 				node_blk->in.nid[i] = 0;
 				need_fix = 1;
-				FIX_MSG("Set double indirect node 0x%x -> 0\n", i);
+				FIX_MSG("Set double indirect node 0x%x -> 0", i);
 			}
 skip:
 			child->pgofs += ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
diff --git a/fsck/mount.c b/fsck/mount.c
index d631547..cf2ef8e 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1981,7 +1981,7 @@ void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
 		if (le32_to_cpu(nid_in_journal(journal, i)) == nid) {
 			memset(&nat_in_journal(journal, i), 0,
 					sizeof(struct f2fs_nat_entry));
-			FIX_MSG("Remove nid [0x%x] in nat journal\n", nid);
+			FIX_MSG("Remove nid [0x%x] in nat journal", nid);
 			return;
 		}
 	}
@@ -2001,6 +2001,7 @@ void nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
 	} else {
 		memset(&nat_block->entries[entry_off], 0,
 					sizeof(struct f2fs_nat_entry));
+		FIX_MSG("Remove nid [0x%x] in NAT", nid);
 	}
 
 	ret = dev_write_block(nat_block, block_addr);
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr
  2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
                   ` (8 preceding siblings ...)
  2017-11-02  3:56 ` [RFC PATCH v2 9/9] fsck.f2fs: format output message of FIX_MSG Sheng Yong
@ 2017-11-02 15:08 ` Chao Yu
  9 siblings, 0 replies; 16+ messages in thread
From: Chao Yu @ 2017-11-02 15:08 UTC (permalink / raw)
  To: Sheng Yong, jaegeuk, yuchao0; +Cc: linux-f2fs-devel

On 2017/11/2 11:56, Sheng Yong wrote:
> v1-v2:
> [PATCH 3] print values of USER/SECRUITY xattr as hex instead of plain text.
> [PATCH 4] replace xattr value if it already exists by setting parameter
>           `flags' as 0 of fsetxattr.
> [PATCH 1/7] move message printing modification into a different patch.
> 
> thanks,
> Sheng
> 
> Sheng Yong (9):
>   fsck.f2fs: do not set fix_on directly
>   fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap
>   dump/fsck: introduce print_xattr_entry
>   dump.f2fs: introduce dump_xattr
>   dump.f2fs: do not dump encrypted files
>   fsck.f2fs: introduce new option --dry-run
>   fsck.f2fs: introduce sanity_check_inode
>   f2fs-tools: remove unused list.h
>   fsck.f2fs: format output message of FIX_MSG

Reviewed-by: Chao Yu <yuchao0@huawei.com>

Thanks,

> 
>  fsck/dump.c       |  93 ++++++++++++++++++++++++++++------
>  fsck/fsck.c       |  25 +++++++++-
>  fsck/fsck.h       |   7 ++-
>  fsck/main.c       |  16 +++++-
>  fsck/mount.c      | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++----
>  fsck/xattr.c      |   2 +-
>  fsck/xattr.h      |  54 +++++++++++++++++++-
>  include/f2fs_fs.h |   1 +
>  include/list.h    |  88 --------------------------------
>  lib/libf2fs.c     |   1 +
>  lib/libf2fs_io.c  |   3 ++
>  11 files changed, 313 insertions(+), 123 deletions(-)
>  delete mode 100644 include/list.h
> 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry
  2017-11-02  3:56 ` [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry Sheng Yong
@ 2017-11-03  3:27   ` Jaegeuk Kim
  2017-11-03  4:08     ` [PATCH v3] " Sheng Yong
  0 siblings, 1 reply; 16+ messages in thread
From: Jaegeuk Kim @ 2017-11-03  3:27 UTC (permalink / raw)
  To: Sheng Yong; +Cc: linux-f2fs-devel

Hi Sheng,

This triggers:

mount.c:14:29: fatal error: linux/posix_acl.h: No such file or directory

Thanks,

On 11/02, Sheng Yong wrote:
> This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
> and introduces print_xattr_entry which tries to parse an xattr entry
> accroding to its xattr index.
> 
> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> ---
>  fsck/dump.c  |  18 ++++-----
>  fsck/fsck.h  |   7 +++-
>  fsck/mount.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  fsck/xattr.c |   2 +-
>  fsck/xattr.h |  54 +++++++++++++++++++++++++-
>  5 files changed, 188 insertions(+), 16 deletions(-)
> 
> diff --git a/fsck/dump.c b/fsck/dump.c
> index 128dc53..90fd073 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
>  	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
>  			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
>  			ni.ino == ni.nid) {
> -		print_node_info(node_blk, force);
> +		print_node_info(sbi, node_blk, force);
>  		dump_file(sbi, &ni, node_blk, force);
>  	} else {
> -		print_node_info(node_blk, force);
> +		print_node_info(sbi, node_blk, force);
>  		MSG(force, "Invalid (i)node block\n\n");
>  	}
>  
>  	free(node_blk);
>  }
>  
> -static void dump_node_from_blkaddr(u32 blk_addr)
> +static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  {
>  	struct f2fs_node *node_blk;
>  	int ret;
> @@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
>  	ASSERT(ret >= 0);
>  
>  	if (c.dbg_lv > 0)
> -		print_node_info(node_blk, 0);
> +		print_node_info(sbi, node_blk, 0);
>  	else
> -		print_inode_info(&node_blk->i, 1);
> +		print_inode_info(sbi, node_blk, 1);
>  
>  	free(node_blk);
>  }
> @@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  
>  	/* print inode */
>  	if (c.dbg_lv > 0)
> -		dump_node_from_blkaddr(ino_ni.blk_addr);
> +		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  
>  	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
>  		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
> @@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  					nid, ni.blk_addr);
>  		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -		dump_node_from_blkaddr(ino_ni.blk_addr);
> +		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  		dump_data_offset(ni.blk_addr,
>  			le16_to_cpu(sum_entry.ofs_in_node));
>  	} else {
> @@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  		if (ni.ino == ni.nid) {
>  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -			dump_node_from_blkaddr(ino_ni.blk_addr);
> +			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  		} else {
>  			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
>  					nid, ni.blk_addr);
>  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -			dump_node_from_blkaddr(ino_ni.blk_addr);
> +			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  			dump_node_offset(ni.blk_addr);
>  		}
>  	}
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index 1e8ed0b..f8caa46 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);
>  
>  extern void update_free_segments(struct f2fs_sb_info *);
>  void print_cp_state(u32);
> -extern void print_node_info(struct f2fs_node *, int);
> -extern void print_inode_info(struct f2fs_inode *, int);
> +extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
> +extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
>  extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
>  extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
>  				unsigned int, int *);
> @@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
>  int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
>  int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
>  
> +/* xattr.c */
> +void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
> +
>  #endif /* _FSCK_H_ */
> diff --git a/fsck/mount.c b/fsck/mount.c
> index d8bc50c..d631547 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -9,7 +9,9 @@
>   * published by the Free Software Foundation.
>   */
>  #include "fsck.h"
> +#include "xattr.h"
>  #include <locale.h>
> +#include <linux/posix_acl.h>
>  
>  u32 get_free_segments(struct f2fs_sb_info *sbi)
>  {
> @@ -35,8 +37,116 @@ void update_free_segments(struct f2fs_sb_info *sbi)
>  	i++;
>  }
>  
> -void print_inode_info(struct f2fs_inode *inode, int name)
> +void print_acl(char *value, int size)
>  {
> +	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
> +	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
> +	const char *end = value + size;
> +	int i, count;
> +
> +	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
> +		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
> +				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
> +		return;
> +	}
> +
> +	count = f2fs_acl_count(size);
> +	if (count <= 0) {
> +		MSG(0, "Invalid ACL value size %d\n", size);
> +		return;
> +	}
> +
> +	for (i = 0; i < count; i++) {
> +		if ((char *)entry > end) {
> +			MSG(0, "Invalid ACL entries count %d\n", count);
> +			return;
> +		}
> +
> +		switch (le16_to_cpu(entry->e_tag)) {
> +		case ACL_USER_OBJ:
> +		case ACL_GROUP_OBJ:
> +		case ACL_MASK:
> +		case ACL_OTHER:
> +			MSG(0, "tag:0x%x perm:0x%x\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry_short));
> +			break;
> +		case ACL_USER:
> +			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm),
> +					le32_to_cpu(entry->e_id));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry));
> +			break;
> +		case ACL_GROUP:
> +			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm),
> +					le32_to_cpu(entry->e_id));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry));
> +			break;
> +		default:
> +			MSG(0, "Unknown ACL tag 0x%x\n",
> +					le16_to_cpu(entry->e_tag));
> +			return;
> +		}
> +	}
> +}
> +
> +void print_xattr_entry(struct f2fs_xattr_entry *ent)
> +{
> +	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
> +	struct fscrypt_context *ctx;
> +	int i;
> +
> +	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
> +	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
> +		MSG(0, "%c", ent->e_name[i]);
> +	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
> +			ent->e_name_len, le16_to_cpu(ent->e_value_size));
> +
> +	switch (ent->e_name_index) {
> +	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
> +	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
> +		print_acl(value, le16_to_cpu(ent->e_value_size));
> +		break;
> +	case F2FS_XATTR_INDEX_USER:
> +	case F2FS_XATTR_INDEX_SECURITY:
> +	case F2FS_XATTR_INDEX_TRUSTED:
> +	case F2FS_XATTR_INDEX_LUSTRE:
> +		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
> +			MSG(0, "%02X", value[i]);
> +		MSG(0, "\n");
> +		break;
> +	case F2FS_XATTR_INDEX_ENCRYPTION:
> +		ctx = (struct fscrypt_context *)value;
> +		MSG(0, "format: %d\n", ctx->format);
> +		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
> +		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
> +		MSG(0, "flags: 0x%x\n", ctx->flags);
> +		MSG(0, "master_key_descriptor: ");
> +		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
> +			MSG(0, "%02X", ctx->master_key_descriptor[i]);
> +		MSG(0, "\nnonce: ");
> +		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
> +			MSG(0, "%02X", ctx->nonce[i]);
> +		MSG(0, "\n");
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +void print_inode_info(struct f2fs_sb_info *sbi,
> +			struct f2fs_node *node, int name)
> +{
> +	struct f2fs_inode *inode = &node->i;
> +	void *xattr_addr;
> +	struct f2fs_xattr_entry *ent;
>  	unsigned char en[F2FS_NAME_LEN + 1];
>  	unsigned int i = 0;
>  	int namelen = le32_to_cpu(inode->i_namelen);
> @@ -111,17 +221,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>  	DISP_u32(inode, i_nid[3]);	/* indirect */
>  	DISP_u32(inode, i_nid[4]);	/* double indirect */
>  
> +	xattr_addr = read_all_xattrs(sbi, node);
> +	list_for_each_xattr(ent, xattr_addr) {
> +		print_xattr_entry(ent);
> +	}
> +	free(xattr_addr);
> +
>  	printf("\n");
>  }
>  
> -void print_node_info(struct f2fs_node *node_block, int verbose)
> +void print_node_info(struct f2fs_sb_info *sbi,
> +			struct f2fs_node *node_block, int verbose)
>  {
>  	nid_t ino = le32_to_cpu(node_block->footer.ino);
>  	nid_t nid = le32_to_cpu(node_block->footer.nid);
>  	/* Is this inode? */
>  	if (ino == nid) {
>  		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
> -		print_inode_info(&node_block->i, verbose);
> +		print_inode_info(sbi, node_block, verbose);
>  	} else {
>  		int i;
>  		u32 *dump_blk = (u32 *)node_block;
> diff --git a/fsck/xattr.c b/fsck/xattr.c
> index 3f5c7d3..1d0f7d3 100644
> --- a/fsck/xattr.c
> +++ b/fsck/xattr.c
> @@ -20,7 +20,7 @@
>  #define XATTR_CREATE 0x1
>  #define XATTR_REPLACE 0x2
>  
> -static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
> +void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
>  {
>  	struct f2fs_xattr_header *header;
>  	void *txattr_addr;
> diff --git a/fsck/xattr.h b/fsck/xattr.h
> index b414629..beed3bb 100644
> --- a/fsck/xattr.h
> +++ b/fsck/xattr.h
> @@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
>  	char e_name[0];		/* attribute name */
>  };
>  
> +#define FS_KEY_DESCRIPTOR_SIZE 8
> +#define FS_KEY_DERIVATION_NONCE_SIZE 16
> +
> +struct fscrypt_context {
> +	u8 format;
> +	u8 contents_encryption_mode;
> +	u8 filenames_encryption_mode;
> +	u8 flags;
> +	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
> +	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
> +} __attribute__((packed));
> +
> +#define F2FS_ACL_VERSION	0x0001
> +
> +struct f2fs_acl_entry {
> +	__le16 e_tag;
> +	__le16 e_perm;
> +	__le32 e_id;
> +};
> +
> +struct f2fs_acl_entry_short {
> +	__le16 e_tag;
> +	__le16 e_perm;
> +};
> +
> +struct f2fs_acl_header {
> +	__le32 a_version;
> +};
> +
> +static inline int f2fs_acl_count(int size)
> +{
> +	ssize_t s;
> +	size -= sizeof(struct f2fs_acl_header);
> +	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
> +	if (s < 0) {
> +		if (size % sizeof(struct f2fs_acl_entry_short))
> +			return -1;
> +		return size / sizeof(struct f2fs_acl_entry_short);
> +	} else {
> +		if (s % sizeof(struct f2fs_acl_entry))
> +			return -1;
> +		return s / sizeof(struct f2fs_acl_entry) + 4;
> +	}
> +}
> +
>  #define XATTR_ROUND	(3)
>  
>  #define XATTR_SELINUX_SUFFIX "selinux"
> -#define F2FS_XATTR_INDEX_SECURITY	6
> +#define F2FS_XATTR_INDEX_USER			1
> +#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
> +#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
> +#define F2FS_XATTR_INDEX_TRUSTED		4
> +#define F2FS_XATTR_INDEX_LUSTRE			5
> +#define F2FS_XATTR_INDEX_SECURITY		6
> +#define F2FS_XATTR_INDEX_ENCRYPTION		9
> +
>  #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
>  
>  #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
> -- 
> 2.11.0

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3] dump/fsck: introduce print_xattr_entry
  2017-11-03  3:27   ` Jaegeuk Kim
@ 2017-11-03  4:08     ` Sheng Yong
  2017-11-03  4:14       ` [PATCH v4] " Sheng Yong
  2017-11-03  4:25       ` [PATCH v5] " Sheng Yong
  0 siblings, 2 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-03  4:08 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel

This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
and introduces print_xattr_entry which tries to parse an xattr entry
accroding to its xattr index.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
v2->v3:
check if <linux/posix_acl.h> is supported. If it is not, print ACL value
in hex format.

  configure.ac |   3 +-
  fsck/dump.c  |  18 ++++----
  fsck/fsck.h  |   7 +++-
  fsck/mount.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  fsck/xattr.c |   2 +-
  fsck/xattr.h |  54 +++++++++++++++++++++++-
  6 files changed, 199 insertions(+), 17 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2fc9260..91bbc9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,7 +92,8 @@ AS_IF([test "x$have_blkid" = "xyes"],

  # Checks for header files.
  AC_CHECK_HEADERS([linux/fs.h linux/blkzoned.h fcntl.h mntent.h stdlib.h string.h \
-		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h])
+		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h \
+		linux/posix_acl.h])

  # Checks for typedefs, structures, and compiler characteristics.
  AC_C_INLINE
diff --git a/fsck/dump.c b/fsck/dump.c
index 128dc53..90fd073 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
  	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
  			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
  			ni.ino == ni.nid) {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
  		dump_file(sbi, &ni, node_blk, force);
  	} else {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
  		MSG(force, "Invalid (i)node block\n\n");
  	}

  	free(node_blk);
  }

-static void dump_node_from_blkaddr(u32 blk_addr)
+static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  {
  	struct f2fs_node *node_blk;
  	int ret;
@@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
  	ASSERT(ret >= 0);

  	if (c.dbg_lv > 0)
-		print_node_info(node_blk, 0);
+		print_node_info(sbi, node_blk, 0);
  	else
-		print_inode_info(&node_blk->i, 1);
+		print_inode_info(sbi, node_blk, 1);

  	free(node_blk);
  }
@@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)

  	/* print inode */
  	if (c.dbg_lv > 0)
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);

  	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
  		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
@@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  					nid, ni.blk_addr);
  		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  		dump_data_offset(ni.blk_addr,
  			le16_to_cpu(sum_entry.ofs_in_node));
  	} else {
@@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  		if (ni.ino == ni.nid) {
  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  		} else {
  			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
  					nid, ni.blk_addr);
  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  			dump_node_offset(ni.blk_addr);
  		}
  	}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1e8ed0b..f8caa46 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);

  extern void update_free_segments(struct f2fs_sb_info *);
  void print_cp_state(u32);
-extern void print_node_info(struct f2fs_node *, int);
-extern void print_inode_info(struct f2fs_inode *, int);
+extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
+extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
  extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
  extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
  				unsigned int, int *);
@@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
  int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
  int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);

+/* xattr.c */
+void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
+
  #endif /* _FSCK_H_ */
diff --git a/fsck/mount.c b/fsck/mount.c
index d8bc50c..c453582 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -9,7 +9,9 @@
   * published by the Free Software Foundation.
   */
  #include "fsck.h"
+#include "xattr.h"
  #include <locale.h>
+#include <linux/posix_acl.h>

  u32 get_free_segments(struct f2fs_sb_info *sbi)
  {
@@ -35,8 +37,125 @@ void update_free_segments(struct f2fs_sb_info *sbi)
  	i++;
  }

-void print_inode_info(struct f2fs_inode *inode, int name)
+#ifdef HAVE_LINUX_POSIX_ACL_H
+void print_acl(char *value, int size)
  {
+	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+	const char *end = value + size;
+	int i, count;
+
+	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
+		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
+				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
+		return;
+	}
+
+	count = f2fs_acl_count(size);
+	if (count <= 0) {
+		MSG(0, "Invalid ACL value size %d\n", size);
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		if ((char *)entry > end) {
+			MSG(0, "Invalid ACL entries count %d\n", count);
+			return;
+		}
+
+		switch (le16_to_cpu(entry->e_tag)) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			MSG(0, "tag:0x%x perm:0x%x\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+		case ACL_USER:
+			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		default:
+			MSG(0, "Unknown ACL tag 0x%x\n",
+					le16_to_cpu(entry->e_tag));
+			return;
+		}
+	}
+}
+#else
+#define print_acl(value, size) do {		\
+	int i;					\
+	for (i = 0; i < size; i++)		\
+		MSG(0, "%02X", value[i]);	\
+	MSG(0, "\n");				\
+} while (0)
+#endif
+
+void print_xattr_entry(struct f2fs_xattr_entry *ent)
+{
+	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
+	struct fscrypt_context *ctx;
+	int i;
+
+	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
+	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
+		MSG(0, "%c", ent->e_name[i]);
+	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
+			ent->e_name_len, le16_to_cpu(ent->e_value_size));
+
+	switch (ent->e_name_index) {
+	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
+	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
+		print_acl(value, le16_to_cpu(ent->e_value_size));
+		break;
+	case F2FS_XATTR_INDEX_USER:
+	case F2FS_XATTR_INDEX_SECURITY:
+	case F2FS_XATTR_INDEX_TRUSTED:
+	case F2FS_XATTR_INDEX_LUSTRE:
+		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
+			MSG(0, "%02X", value[i]);
+		MSG(0, "\n");
+		break;
+	case F2FS_XATTR_INDEX_ENCRYPTION:
+		ctx = (struct fscrypt_context *)value;
+		MSG(0, "format: %d\n", ctx->format);
+		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
+		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
+		MSG(0, "flags: 0x%x\n", ctx->flags);
+		MSG(0, "master_key_descriptor: ");
+		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
+			MSG(0, "%02X", ctx->master_key_descriptor[i]);
+		MSG(0, "\nnonce: ");
+		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
+			MSG(0, "%02X", ctx->nonce[i]);
+		MSG(0, "\n");
+		break;
+	default:
+		break;
+	}
+}
+
+void print_inode_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node, int name)
+{
+	struct f2fs_inode *inode = &node->i;
+	void *xattr_addr;
+	struct f2fs_xattr_entry *ent;
  	unsigned char en[F2FS_NAME_LEN + 1];
  	unsigned int i = 0;
  	int namelen = le32_to_cpu(inode->i_namelen);
@@ -111,17 +230,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
  	DISP_u32(inode, i_nid[3]);	/* indirect */
  	DISP_u32(inode, i_nid[4]);	/* double indirect */

+	xattr_addr = read_all_xattrs(sbi, node);
+	list_for_each_xattr(ent, xattr_addr) {
+		print_xattr_entry(ent);
+	}
+	free(xattr_addr);
+
  	printf("\n");
  }

-void print_node_info(struct f2fs_node *node_block, int verbose)
+void print_node_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node_block, int verbose)
  {
  	nid_t ino = le32_to_cpu(node_block->footer.ino);
  	nid_t nid = le32_to_cpu(node_block->footer.nid);
  	/* Is this inode? */
  	if (ino == nid) {
  		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
-		print_inode_info(&node_block->i, verbose);
+		print_inode_info(sbi, node_block, verbose);
  	} else {
  		int i;
  		u32 *dump_blk = (u32 *)node_block;
diff --git a/fsck/xattr.c b/fsck/xattr.c
index 3f5c7d3..1d0f7d3 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -20,7 +20,7 @@
  #define XATTR_CREATE 0x1
  #define XATTR_REPLACE 0x2

-static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
+void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
  {
  	struct f2fs_xattr_header *header;
  	void *txattr_addr;
diff --git a/fsck/xattr.h b/fsck/xattr.h
index b414629..beed3bb 100644
--- a/fsck/xattr.h
+++ b/fsck/xattr.h
@@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
  	char e_name[0];		/* attribute name */
  };

+#define FS_KEY_DESCRIPTOR_SIZE 8
+#define FS_KEY_DERIVATION_NONCE_SIZE 16
+
+struct fscrypt_context {
+	u8 format;
+	u8 contents_encryption_mode;
+	u8 filenames_encryption_mode;
+	u8 flags;
+	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+} __attribute__((packed));
+
+#define F2FS_ACL_VERSION	0x0001
+
+struct f2fs_acl_entry {
+	__le16 e_tag;
+	__le16 e_perm;
+	__le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+	__le16 e_tag;
+	__le16 e_perm;
+};
+
+struct f2fs_acl_header {
+	__le32 a_version;
+};
+
+static inline int f2fs_acl_count(int size)
+{
+	ssize_t s;
+	size -= sizeof(struct f2fs_acl_header);
+	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct f2fs_acl_entry_short))
+			return -1;
+		return size / sizeof(struct f2fs_acl_entry_short);
+	} else {
+		if (s % sizeof(struct f2fs_acl_entry))
+			return -1;
+		return s / sizeof(struct f2fs_acl_entry) + 4;
+	}
+}
+
  #define XATTR_ROUND	(3)

  #define XATTR_SELINUX_SUFFIX "selinux"
-#define F2FS_XATTR_INDEX_SECURITY	6
+#define F2FS_XATTR_INDEX_USER			1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define F2FS_XATTR_INDEX_TRUSTED		4
+#define F2FS_XATTR_INDEX_LUSTRE			5
+#define F2FS_XATTR_INDEX_SECURITY		6
+#define F2FS_XATTR_INDEX_ENCRYPTION		9
+
  #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)

  #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4] dump/fsck: introduce print_xattr_entry
  2017-11-03  4:08     ` [PATCH v3] " Sheng Yong
@ 2017-11-03  4:14       ` Sheng Yong
  2017-11-03  4:25       ` [PATCH v5] " Sheng Yong
  1 sibling, 0 replies; 16+ messages in thread
From: Sheng Yong @ 2017-11-03  4:14 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel

This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
and introduces print_xattr_entry which tries to parse an xattr entry
accroding to its xattr index.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
v3->v4:
Please ignore the previous [PATCH v3] because of the bad indent. Sorry
for the noise :(

v2->v3:
check if <linux/posix_acl.h> is supported. If it is not, print ACL value
in hex format.

thanks,
Sheng

  configure.ac |   3 +-
  fsck/dump.c  |  18 ++++----
  fsck/fsck.h  |   7 +++-
  fsck/mount.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  fsck/xattr.c |   2 +-
  fsck/xattr.h |  54 +++++++++++++++++++++++-
  6 files changed, 199 insertions(+), 17 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2fc9260..91bbc9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,7 +92,8 @@ AS_IF([test "x$have_blkid" = "xyes"],

  # Checks for header files.
  AC_CHECK_HEADERS([linux/fs.h linux/blkzoned.h fcntl.h mntent.h stdlib.h string.h \
-		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h])
+		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h \
+		linux/posix_acl.h])

  # Checks for typedefs, structures, and compiler characteristics.
  AC_C_INLINE
diff --git a/fsck/dump.c b/fsck/dump.c
index 128dc53..90fd073 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
  	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
  			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
  			ni.ino == ni.nid) {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
  		dump_file(sbi, &ni, node_blk, force);
  	} else {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
  		MSG(force, "Invalid (i)node block\n\n");
  	}

  	free(node_blk);
  }

-static void dump_node_from_blkaddr(u32 blk_addr)
+static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  {
  	struct f2fs_node *node_blk;
  	int ret;
@@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
  	ASSERT(ret >= 0);

  	if (c.dbg_lv > 0)
-		print_node_info(node_blk, 0);
+		print_node_info(sbi, node_blk, 0);
  	else
-		print_inode_info(&node_blk->i, 1);
+		print_inode_info(sbi, node_blk, 1);

  	free(node_blk);
  }
@@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)

  	/* print inode */
  	if (c.dbg_lv > 0)
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);

  	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
  		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
@@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  					nid, ni.blk_addr);
  		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  		dump_data_offset(ni.blk_addr,
  			le16_to_cpu(sum_entry.ofs_in_node));
  	} else {
@@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
  		if (ni.ino == ni.nid) {
  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  		} else {
  			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
  					nid, ni.blk_addr);
  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
  					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
  			dump_node_offset(ni.blk_addr);
  		}
  	}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1e8ed0b..f8caa46 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);

  extern void update_free_segments(struct f2fs_sb_info *);
  void print_cp_state(u32);
-extern void print_node_info(struct f2fs_node *, int);
-extern void print_inode_info(struct f2fs_inode *, int);
+extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
+extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
  extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
  extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
  				unsigned int, int *);
@@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
  int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
  int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);

+/* xattr.c */
+void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
+
  #endif /* _FSCK_H_ */
diff --git a/fsck/mount.c b/fsck/mount.c
index d8bc50c..c453582 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -9,7 +9,9 @@
   * published by the Free Software Foundation.
   */
  #include "fsck.h"
+#include "xattr.h"
  #include <locale.h>
+#include <linux/posix_acl.h>

  u32 get_free_segments(struct f2fs_sb_info *sbi)
  {
@@ -35,8 +37,125 @@ void update_free_segments(struct f2fs_sb_info *sbi)
  	i++;
  }

-void print_inode_info(struct f2fs_inode *inode, int name)
+#ifdef HAVE_LINUX_POSIX_ACL_H
+void print_acl(char *value, int size)
  {
+	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+	const char *end = value + size;
+	int i, count;
+
+	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
+		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
+				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
+		return;
+	}
+
+	count = f2fs_acl_count(size);
+	if (count <= 0) {
+		MSG(0, "Invalid ACL value size %d\n", size);
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		if ((char *)entry > end) {
+			MSG(0, "Invalid ACL entries count %d\n", count);
+			return;
+		}
+
+		switch (le16_to_cpu(entry->e_tag)) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			MSG(0, "tag:0x%x perm:0x%x\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+		case ACL_USER:
+			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		default:
+			MSG(0, "Unknown ACL tag 0x%x\n",
+					le16_to_cpu(entry->e_tag));
+			return;
+		}
+	}
+}
+#else
+#define print_acl(value, size) do {		\
+	int i;					\
+	for (i = 0; i < size; i++)		\
+		MSG(0, "%02X", value[i]);	\
+	MSG(0, "\n");				\
+} while (0)
+#endif
+
+void print_xattr_entry(struct f2fs_xattr_entry *ent)
+{
+	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
+	struct fscrypt_context *ctx;
+	int i;
+
+	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
+	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
+		MSG(0, "%c", ent->e_name[i]);
+	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
+			ent->e_name_len, le16_to_cpu(ent->e_value_size));
+
+	switch (ent->e_name_index) {
+	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
+	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
+		print_acl(value, le16_to_cpu(ent->e_value_size));
+		break;
+	case F2FS_XATTR_INDEX_USER:
+	case F2FS_XATTR_INDEX_SECURITY:
+	case F2FS_XATTR_INDEX_TRUSTED:
+	case F2FS_XATTR_INDEX_LUSTRE:
+		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
+			MSG(0, "%02X", value[i]);
+		MSG(0, "\n");
+		break;
+	case F2FS_XATTR_INDEX_ENCRYPTION:
+		ctx = (struct fscrypt_context *)value;
+		MSG(0, "format: %d\n", ctx->format);
+		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
+		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
+		MSG(0, "flags: 0x%x\n", ctx->flags);
+		MSG(0, "master_key_descriptor: ");
+		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
+			MSG(0, "%02X", ctx->master_key_descriptor[i]);
+		MSG(0, "\nnonce: ");
+		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
+			MSG(0, "%02X", ctx->nonce[i]);
+		MSG(0, "\n");
+		break;
+	default:
+		break;
+	}
+}
+
+void print_inode_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node, int name)
+{
+	struct f2fs_inode *inode = &node->i;
+	void *xattr_addr;
+	struct f2fs_xattr_entry *ent;
  	unsigned char en[F2FS_NAME_LEN + 1];
  	unsigned int i = 0;
  	int namelen = le32_to_cpu(inode->i_namelen);
@@ -111,17 +230,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
  	DISP_u32(inode, i_nid[3]);	/* indirect */
  	DISP_u32(inode, i_nid[4]);	/* double indirect */

+	xattr_addr = read_all_xattrs(sbi, node);
+	list_for_each_xattr(ent, xattr_addr) {
+		print_xattr_entry(ent);
+	}
+	free(xattr_addr);
+
  	printf("\n");
  }

-void print_node_info(struct f2fs_node *node_block, int verbose)
+void print_node_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node_block, int verbose)
  {
  	nid_t ino = le32_to_cpu(node_block->footer.ino);
  	nid_t nid = le32_to_cpu(node_block->footer.nid);
  	/* Is this inode? */
  	if (ino == nid) {
  		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
-		print_inode_info(&node_block->i, verbose);
+		print_inode_info(sbi, node_block, verbose);
  	} else {
  		int i;
  		u32 *dump_blk = (u32 *)node_block;
diff --git a/fsck/xattr.c b/fsck/xattr.c
index 3f5c7d3..1d0f7d3 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -20,7 +20,7 @@
  #define XATTR_CREATE 0x1
  #define XATTR_REPLACE 0x2

-static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
+void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
  {
  	struct f2fs_xattr_header *header;
  	void *txattr_addr;
diff --git a/fsck/xattr.h b/fsck/xattr.h
index b414629..beed3bb 100644
--- a/fsck/xattr.h
+++ b/fsck/xattr.h
@@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
  	char e_name[0];		/* attribute name */
  };

+#define FS_KEY_DESCRIPTOR_SIZE 8
+#define FS_KEY_DERIVATION_NONCE_SIZE 16
+
+struct fscrypt_context {
+	u8 format;
+	u8 contents_encryption_mode;
+	u8 filenames_encryption_mode;
+	u8 flags;
+	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+} __attribute__((packed));
+
+#define F2FS_ACL_VERSION	0x0001
+
+struct f2fs_acl_entry {
+	__le16 e_tag;
+	__le16 e_perm;
+	__le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+	__le16 e_tag;
+	__le16 e_perm;
+};
+
+struct f2fs_acl_header {
+	__le32 a_version;
+};
+
+static inline int f2fs_acl_count(int size)
+{
+	ssize_t s;
+	size -= sizeof(struct f2fs_acl_header);
+	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct f2fs_acl_entry_short))
+			return -1;
+		return size / sizeof(struct f2fs_acl_entry_short);
+	} else {
+		if (s % sizeof(struct f2fs_acl_entry))
+			return -1;
+		return s / sizeof(struct f2fs_acl_entry) + 4;
+	}
+}
+
  #define XATTR_ROUND	(3)

  #define XATTR_SELINUX_SUFFIX "selinux"
-#define F2FS_XATTR_INDEX_SECURITY	6
+#define F2FS_XATTR_INDEX_USER			1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define F2FS_XATTR_INDEX_TRUSTED		4
+#define F2FS_XATTR_INDEX_LUSTRE			5
+#define F2FS_XATTR_INDEX_SECURITY		6
+#define F2FS_XATTR_INDEX_ENCRYPTION		9
+
  #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)

  #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
-- 
2.11.0




------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5] dump/fsck: introduce print_xattr_entry
  2017-11-03  4:08     ` [PATCH v3] " Sheng Yong
  2017-11-03  4:14       ` [PATCH v4] " Sheng Yong
@ 2017-11-03  4:25       ` Sheng Yong
  2017-11-03 18:24         ` Jaegeuk Kim
  1 sibling, 1 reply; 16+ messages in thread
From: Sheng Yong @ 2017-11-03  4:25 UTC (permalink / raw)
  To: jaegeuk, yuchao0; +Cc: shengyong1, linux-f2fs-devel

This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
and introduces print_xattr_entry which tries to parse an xattr entry
accroding to its xattr index.

Signed-off-by: Sheng Yong <shengyong1@huawei.com>
---
v3->v5:
Please ignore the previous [PATCH v3/v4] because of the bad indent (some
configure of my email client may be not correct). Sorry for the noise :(

v2->v3:
check if <linux/posix_acl.h> is supported. If it is not, print ACL value
in hex format.

thanks,
Sheng
 configure.ac |   3 +-
 fsck/dump.c  |  18 ++++----
 fsck/fsck.h  |   7 +++-
 fsck/mount.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 fsck/xattr.c |   2 +-
 fsck/xattr.h |  54 +++++++++++++++++++++++-
 6 files changed, 199 insertions(+), 17 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2fc9260..91bbc9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,7 +92,8 @@ AS_IF([test "x$have_blkid" = "xyes"],
 
 # Checks for header files.
 AC_CHECK_HEADERS([linux/fs.h linux/blkzoned.h fcntl.h mntent.h stdlib.h string.h \
-		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h])
+		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h \
+		linux/posix_acl.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_INLINE
diff --git a/fsck/dump.c b/fsck/dump.c
index 128dc53..90fd073 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
 	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
 			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
 			ni.ino == ni.nid) {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
 		dump_file(sbi, &ni, node_blk, force);
 	} else {
-		print_node_info(node_blk, force);
+		print_node_info(sbi, node_blk, force);
 		MSG(force, "Invalid (i)node block\n\n");
 	}
 
 	free(node_blk);
 }
 
-static void dump_node_from_blkaddr(u32 blk_addr)
+static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 {
 	struct f2fs_node *node_blk;
 	int ret;
@@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
 	ASSERT(ret >= 0);
 
 	if (c.dbg_lv > 0)
-		print_node_info(node_blk, 0);
+		print_node_info(sbi, node_blk, 0);
 	else
-		print_inode_info(&node_blk->i, 1);
+		print_inode_info(sbi, node_blk, 1);
 
 	free(node_blk);
 }
@@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 
 	/* print inode */
 	if (c.dbg_lv > 0)
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 
 	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
 		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
@@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 					nid, ni.blk_addr);
 		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-		dump_node_from_blkaddr(ino_ni.blk_addr);
+		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 		dump_data_offset(ni.blk_addr,
 			le16_to_cpu(sum_entry.ofs_in_node));
 	} else {
@@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
 		if (ni.ino == ni.nid) {
 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 		} else {
 			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
 					nid, ni.blk_addr);
 			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
 					ni.ino, ino_ni.blk_addr);
-			dump_node_from_blkaddr(ino_ni.blk_addr);
+			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
 			dump_node_offset(ni.blk_addr);
 		}
 	}
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 1e8ed0b..f8caa46 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);
 
 extern void update_free_segments(struct f2fs_sb_info *);
 void print_cp_state(u32);
-extern void print_node_info(struct f2fs_node *, int);
-extern void print_inode_info(struct f2fs_inode *, int);
+extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
+extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
 extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
 extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
 				unsigned int, int *);
@@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
 int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
 int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
 
+/* xattr.c */
+void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
+
 #endif /* _FSCK_H_ */
diff --git a/fsck/mount.c b/fsck/mount.c
index d8bc50c..c453582 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -9,7 +9,9 @@
  * published by the Free Software Foundation.
  */
 #include "fsck.h"
+#include "xattr.h"
 #include <locale.h>
+#include <linux/posix_acl.h>
 
 u32 get_free_segments(struct f2fs_sb_info *sbi)
 {
@@ -35,8 +37,125 @@ void update_free_segments(struct f2fs_sb_info *sbi)
 	i++;
 }
 
-void print_inode_info(struct f2fs_inode *inode, int name)
+#ifdef HAVE_LINUX_POSIX_ACL_H
+void print_acl(char *value, int size)
 {
+	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+	const char *end = value + size;
+	int i, count;
+
+	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
+		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
+				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
+		return;
+	}
+
+	count = f2fs_acl_count(size);
+	if (count <= 0) {
+		MSG(0, "Invalid ACL value size %d\n", size);
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		if ((char *)entry > end) {
+			MSG(0, "Invalid ACL entries count %d\n", count);
+			return;
+		}
+
+		switch (le16_to_cpu(entry->e_tag)) {
+		case ACL_USER_OBJ:
+		case ACL_GROUP_OBJ:
+		case ACL_MASK:
+		case ACL_OTHER:
+			MSG(0, "tag:0x%x perm:0x%x\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry_short));
+			break;
+		case ACL_USER:
+			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		case ACL_GROUP:
+			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
+					le16_to_cpu(entry->e_tag),
+					le16_to_cpu(entry->e_perm),
+					le32_to_cpu(entry->e_id));
+			entry = (struct f2fs_acl_entry *)((char *)entry +
+					sizeof(struct f2fs_acl_entry));
+			break;
+		default:
+			MSG(0, "Unknown ACL tag 0x%x\n",
+					le16_to_cpu(entry->e_tag));
+			return;
+		}
+	}
+}
+#else
+#define print_acl(value, size) do {		\
+	int i;					\
+	for (i = 0; i < size; i++)		\
+		MSG(0, "%02X", value[i]);	\
+	MSG(0, "\n");				\
+} while (0)
+#endif
+
+void print_xattr_entry(struct f2fs_xattr_entry *ent)
+{
+	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
+	struct fscrypt_context *ctx;
+	int i;
+
+	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
+	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
+		MSG(0, "%c", ent->e_name[i]);
+	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
+			ent->e_name_len, le16_to_cpu(ent->e_value_size));
+
+	switch (ent->e_name_index) {
+	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
+	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
+		print_acl(value, le16_to_cpu(ent->e_value_size));
+		break;
+	case F2FS_XATTR_INDEX_USER:
+	case F2FS_XATTR_INDEX_SECURITY:
+	case F2FS_XATTR_INDEX_TRUSTED:
+	case F2FS_XATTR_INDEX_LUSTRE:
+		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
+			MSG(0, "%02X", value[i]);
+		MSG(0, "\n");
+		break;
+	case F2FS_XATTR_INDEX_ENCRYPTION:
+		ctx = (struct fscrypt_context *)value;
+		MSG(0, "format: %d\n", ctx->format);
+		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
+		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
+		MSG(0, "flags: 0x%x\n", ctx->flags);
+		MSG(0, "master_key_descriptor: ");
+		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
+			MSG(0, "%02X", ctx->master_key_descriptor[i]);
+		MSG(0, "\nnonce: ");
+		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
+			MSG(0, "%02X", ctx->nonce[i]);
+		MSG(0, "\n");
+		break;
+	default:
+		break;
+	}
+}
+
+void print_inode_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node, int name)
+{
+	struct f2fs_inode *inode = &node->i;
+	void *xattr_addr;
+	struct f2fs_xattr_entry *ent;
 	unsigned char en[F2FS_NAME_LEN + 1];
 	unsigned int i = 0;
 	int namelen = le32_to_cpu(inode->i_namelen);
@@ -111,17 +230,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
 	DISP_u32(inode, i_nid[3]);	/* indirect */
 	DISP_u32(inode, i_nid[4]);	/* double indirect */
 
+	xattr_addr = read_all_xattrs(sbi, node);
+	list_for_each_xattr(ent, xattr_addr) {
+		print_xattr_entry(ent);
+	}
+	free(xattr_addr);
+
 	printf("\n");
 }
 
-void print_node_info(struct f2fs_node *node_block, int verbose)
+void print_node_info(struct f2fs_sb_info *sbi,
+			struct f2fs_node *node_block, int verbose)
 {
 	nid_t ino = le32_to_cpu(node_block->footer.ino);
 	nid_t nid = le32_to_cpu(node_block->footer.nid);
 	/* Is this inode? */
 	if (ino == nid) {
 		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
-		print_inode_info(&node_block->i, verbose);
+		print_inode_info(sbi, node_block, verbose);
 	} else {
 		int i;
 		u32 *dump_blk = (u32 *)node_block;
diff --git a/fsck/xattr.c b/fsck/xattr.c
index 3f5c7d3..1d0f7d3 100644
--- a/fsck/xattr.c
+++ b/fsck/xattr.c
@@ -20,7 +20,7 @@
 #define XATTR_CREATE 0x1
 #define XATTR_REPLACE 0x2
 
-static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
+void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
 {
 	struct f2fs_xattr_header *header;
 	void *txattr_addr;
diff --git a/fsck/xattr.h b/fsck/xattr.h
index b414629..beed3bb 100644
--- a/fsck/xattr.h
+++ b/fsck/xattr.h
@@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
 	char e_name[0];		/* attribute name */
 };
 
+#define FS_KEY_DESCRIPTOR_SIZE 8
+#define FS_KEY_DERIVATION_NONCE_SIZE 16
+
+struct fscrypt_context {
+	u8 format;
+	u8 contents_encryption_mode;
+	u8 filenames_encryption_mode;
+	u8 flags;
+	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+} __attribute__((packed));
+
+#define F2FS_ACL_VERSION	0x0001
+
+struct f2fs_acl_entry {
+	__le16 e_tag;
+	__le16 e_perm;
+	__le32 e_id;
+};
+
+struct f2fs_acl_entry_short {
+	__le16 e_tag;
+	__le16 e_perm;
+};
+
+struct f2fs_acl_header {
+	__le32 a_version;
+};
+
+static inline int f2fs_acl_count(int size)
+{
+	ssize_t s;
+	size -= sizeof(struct f2fs_acl_header);
+	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct f2fs_acl_entry_short))
+			return -1;
+		return size / sizeof(struct f2fs_acl_entry_short);
+	} else {
+		if (s % sizeof(struct f2fs_acl_entry))
+			return -1;
+		return s / sizeof(struct f2fs_acl_entry) + 4;
+	}
+}
+
 #define XATTR_ROUND	(3)
 
 #define XATTR_SELINUX_SUFFIX "selinux"
-#define F2FS_XATTR_INDEX_SECURITY	6
+#define F2FS_XATTR_INDEX_USER			1
+#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
+#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define F2FS_XATTR_INDEX_TRUSTED		4
+#define F2FS_XATTR_INDEX_LUSTRE			5
+#define F2FS_XATTR_INDEX_SECURITY		6
+#define F2FS_XATTR_INDEX_ENCRYPTION		9
+
 #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
 
 #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v5] dump/fsck: introduce print_xattr_entry
  2017-11-03  4:25       ` [PATCH v5] " Sheng Yong
@ 2017-11-03 18:24         ` Jaegeuk Kim
  0 siblings, 0 replies; 16+ messages in thread
From: Jaegeuk Kim @ 2017-11-03 18:24 UTC (permalink / raw)
  To: Sheng Yong; +Cc: linux-f2fs-devel

On 11/03, Sheng Yong wrote:
> This patch exports read_all_xattrs to allow dump/fsck to get all xattrs,
> and introduces print_xattr_entry which tries to parse an xattr entry
> accroding to its xattr index.
> 
> Signed-off-by: Sheng Yong <shengyong1@huawei.com>
> ---
> v3->v5:
> Please ignore the previous [PATCH v3/v4] because of the bad indent (some
> configure of my email client may be not correct). Sorry for the noise :(
> 
> v2->v3:
> check if <linux/posix_acl.h> is supported. If it is not, print ACL value
> in hex format.
> 
> thanks,
> Sheng
>  configure.ac |   3 +-
>  fsck/dump.c  |  18 ++++----
>  fsck/fsck.h  |   7 +++-
>  fsck/mount.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  fsck/xattr.c |   2 +-
>  fsck/xattr.h |  54 +++++++++++++++++++++++-
>  6 files changed, 199 insertions(+), 17 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 2fc9260..91bbc9c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -92,7 +92,8 @@ AS_IF([test "x$have_blkid" = "xyes"],
>  
>  # Checks for header files.
>  AC_CHECK_HEADERS([linux/fs.h linux/blkzoned.h fcntl.h mntent.h stdlib.h string.h \
> -		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h])
> +		sys/ioctl.h sys/mount.h unistd.h linux/falloc.h byteswap.h \
> +		linux/posix_acl.h])
>  
>  # Checks for typedefs, structures, and compiler characteristics.
>  AC_C_INLINE
> diff --git a/fsck/dump.c b/fsck/dump.c
> index 128dc53..90fd073 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -419,17 +419,17 @@ void dump_node(struct f2fs_sb_info *sbi, nid_t nid, int force)
>  	if (le32_to_cpu(node_blk->footer.ino) == ni.ino &&
>  			le32_to_cpu(node_blk->footer.nid) == ni.nid &&
>  			ni.ino == ni.nid) {
> -		print_node_info(node_blk, force);
> +		print_node_info(sbi, node_blk, force);
>  		dump_file(sbi, &ni, node_blk, force);
>  	} else {
> -		print_node_info(node_blk, force);
> +		print_node_info(sbi, node_blk, force);
>  		MSG(force, "Invalid (i)node block\n\n");
>  	}
>  
>  	free(node_blk);
>  }
>  
> -static void dump_node_from_blkaddr(u32 blk_addr)
> +static void dump_node_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  {
>  	struct f2fs_node *node_blk;
>  	int ret;
> @@ -441,9 +441,9 @@ static void dump_node_from_blkaddr(u32 blk_addr)
>  	ASSERT(ret >= 0);
>  
>  	if (c.dbg_lv > 0)
> -		print_node_info(node_blk, 0);
> +		print_node_info(sbi, node_blk, 0);
>  	else
> -		print_inode_info(&node_blk->i, 1);
> +		print_inode_info(sbi, node_blk, 1);
>  
>  	free(node_blk);
>  }
> @@ -567,7 +567,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  
>  	/* print inode */
>  	if (c.dbg_lv > 0)
> -		dump_node_from_blkaddr(ino_ni.blk_addr);
> +		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  
>  	if (type == SEG_TYPE_CUR_DATA || type == SEG_TYPE_DATA) {
>  		MSG(0, "FS Userdata Area: Data block from 0x%x\n", blk_addr);
> @@ -575,7 +575,7 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  					nid, ni.blk_addr);
>  		MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -		dump_node_from_blkaddr(ino_ni.blk_addr);
> +		dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  		dump_data_offset(ni.blk_addr,
>  			le16_to_cpu(sum_entry.ofs_in_node));
>  	} else {
> @@ -583,13 +583,13 @@ int dump_info_from_blkaddr(struct f2fs_sb_info *sbi, u32 blk_addr)
>  		if (ni.ino == ni.nid) {
>  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -			dump_node_from_blkaddr(ino_ni.blk_addr);
> +			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  		} else {
>  			MSG(0, " - Node block        : id = 0x%x from 0x%x\n",
>  					nid, ni.blk_addr);
>  			MSG(0, " - Inode block       : id = 0x%x from 0x%x\n",
>  					ni.ino, ino_ni.blk_addr);
> -			dump_node_from_blkaddr(ino_ni.blk_addr);
> +			dump_node_from_blkaddr(sbi, ino_ni.blk_addr);
>  			dump_node_offset(ni.blk_addr);
>  		}
>  	}
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index 1e8ed0b..f8caa46 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -141,8 +141,8 @@ int convert_encrypted_name(unsigned char *, int, unsigned char *, int);
>  
>  extern void update_free_segments(struct f2fs_sb_info *);
>  void print_cp_state(u32);
> -extern void print_node_info(struct f2fs_node *, int);
> -extern void print_inode_info(struct f2fs_inode *, int);
> +extern void print_node_info(struct f2fs_sb_info *, struct f2fs_node *, int);
> +extern void print_inode_info(struct f2fs_sb_info *, struct f2fs_node *, int);
>  extern struct seg_entry *get_seg_entry(struct f2fs_sb_info *, unsigned int);
>  extern struct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *,
>  				unsigned int, int *);
> @@ -228,4 +228,7 @@ int f2fs_symlink(struct f2fs_sb_info *, struct dentry *);
>  int inode_set_selinux(struct f2fs_sb_info *, u32, const char *);
>  int f2fs_find_path(struct f2fs_sb_info *, char *, nid_t *);
>  
> +/* xattr.c */
> +void *read_all_xattrs(struct f2fs_sb_info *, struct f2fs_node *);
> +
>  #endif /* _FSCK_H_ */
> diff --git a/fsck/mount.c b/fsck/mount.c
> index d8bc50c..c453582 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -9,7 +9,9 @@
>   * published by the Free Software Foundation.
>   */
>  #include "fsck.h"
> +#include "xattr.h"
>  #include <locale.h>
> +#include <linux/posix_acl.h>

Still build failure. We can use <sys/acl.h>

>  
>  u32 get_free_segments(struct f2fs_sb_info *sbi)
>  {
> @@ -35,8 +37,125 @@ void update_free_segments(struct f2fs_sb_info *sbi)
>  	i++;
>  }
>  
> -void print_inode_info(struct f2fs_inode *inode, int name)
> +#ifdef HAVE_LINUX_POSIX_ACL_H
> +void print_acl(char *value, int size)
>  {
> +	struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
> +	struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
> +	const char *end = value + size;
> +	int i, count;
> +
> +	if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) {
> +		MSG(0, "Invalid ACL version [0x%x : 0x%x]\n",
> +				le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION);
> +		return;
> +	}
> +
> +	count = f2fs_acl_count(size);
> +	if (count <= 0) {
> +		MSG(0, "Invalid ACL value size %d\n", size);
> +		return;
> +	}
> +
> +	for (i = 0; i < count; i++) {
> +		if ((char *)entry > end) {
> +			MSG(0, "Invalid ACL entries count %d\n", count);
> +			return;
> +		}
> +
> +		switch (le16_to_cpu(entry->e_tag)) {
> +		case ACL_USER_OBJ:
> +		case ACL_GROUP_OBJ:
> +		case ACL_MASK:
> +		case ACL_OTHER:
> +			MSG(0, "tag:0x%x perm:0x%x\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry_short));
> +			break;
> +		case ACL_USER:
> +			MSG(0, "tag:0x%x perm:0x%x uid:%u\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm),
> +					le32_to_cpu(entry->e_id));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry));
> +			break;
> +		case ACL_GROUP:
> +			MSG(0, "tag:0x%x perm:0x%x gid:%u\n",
> +					le16_to_cpu(entry->e_tag),
> +					le16_to_cpu(entry->e_perm),
> +					le32_to_cpu(entry->e_id));
> +			entry = (struct f2fs_acl_entry *)((char *)entry +
> +					sizeof(struct f2fs_acl_entry));
> +			break;
> +		default:
> +			MSG(0, "Unknown ACL tag 0x%x\n",
> +					le16_to_cpu(entry->e_tag));
> +			return;
> +		}
> +	}
> +}
> +#else
> +#define print_acl(value, size) do {		\
> +	int i;					\
> +	for (i = 0; i < size; i++)		\
> +		MSG(0, "%02X", value[i]);	\
> +	MSG(0, "\n");				\
> +} while (0)
> +#endif
> +
> +void print_xattr_entry(struct f2fs_xattr_entry *ent)
> +{
> +	char *value = (char *)(ent->e_name + le16_to_cpu(ent->e_name_len));
> +	struct fscrypt_context *ctx;
> +	int i;
> +
> +	MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index);
> +	for (i = 0; i < le16_to_cpu(ent->e_name_len); i++)
> +		MSG(0, "%c", ent->e_name[i]);
> +	MSG(0, " e_name_len:%d e_value_size:%d e_value:\n",
> +			ent->e_name_len, le16_to_cpu(ent->e_value_size));
> +
> +	switch (ent->e_name_index) {
> +	case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS:
> +	case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT:
> +		print_acl(value, le16_to_cpu(ent->e_value_size));
> +		break;
> +	case F2FS_XATTR_INDEX_USER:
> +	case F2FS_XATTR_INDEX_SECURITY:
> +	case F2FS_XATTR_INDEX_TRUSTED:
> +	case F2FS_XATTR_INDEX_LUSTRE:
> +		for (i = 0; i < le16_to_cpu(ent->e_value_size); i++)
> +			MSG(0, "%02X", value[i]);
> +		MSG(0, "\n");
> +		break;
> +	case F2FS_XATTR_INDEX_ENCRYPTION:
> +		ctx = (struct fscrypt_context *)value;
> +		MSG(0, "format: %d\n", ctx->format);
> +		MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode);
> +		MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode);
> +		MSG(0, "flags: 0x%x\n", ctx->flags);
> +		MSG(0, "master_key_descriptor: ");
> +		for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++)
> +			MSG(0, "%02X", ctx->master_key_descriptor[i]);
> +		MSG(0, "\nnonce: ");
> +		for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++)
> +			MSG(0, "%02X", ctx->nonce[i]);
> +		MSG(0, "\n");
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +void print_inode_info(struct f2fs_sb_info *sbi,
> +			struct f2fs_node *node, int name)
> +{
> +	struct f2fs_inode *inode = &node->i;
> +	void *xattr_addr;
> +	struct f2fs_xattr_entry *ent;
>  	unsigned char en[F2FS_NAME_LEN + 1];
>  	unsigned int i = 0;
>  	int namelen = le32_to_cpu(inode->i_namelen);
> @@ -111,17 +230,24 @@ void print_inode_info(struct f2fs_inode *inode, int name)
>  	DISP_u32(inode, i_nid[3]);	/* indirect */
>  	DISP_u32(inode, i_nid[4]);	/* double indirect */
>  
> +	xattr_addr = read_all_xattrs(sbi, node);
> +	list_for_each_xattr(ent, xattr_addr) {
> +		print_xattr_entry(ent);
> +	}
> +	free(xattr_addr);
> +
>  	printf("\n");
>  }
>  
> -void print_node_info(struct f2fs_node *node_block, int verbose)
> +void print_node_info(struct f2fs_sb_info *sbi,
> +			struct f2fs_node *node_block, int verbose)
>  {
>  	nid_t ino = le32_to_cpu(node_block->footer.ino);
>  	nid_t nid = le32_to_cpu(node_block->footer.nid);
>  	/* Is this inode? */
>  	if (ino == nid) {
>  		DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid);
> -		print_inode_info(&node_block->i, verbose);
> +		print_inode_info(sbi, node_block, verbose);
>  	} else {
>  		int i;
>  		u32 *dump_blk = (u32 *)node_block;
> diff --git a/fsck/xattr.c b/fsck/xattr.c
> index 3f5c7d3..1d0f7d3 100644
> --- a/fsck/xattr.c
> +++ b/fsck/xattr.c
> @@ -20,7 +20,7 @@
>  #define XATTR_CREATE 0x1
>  #define XATTR_REPLACE 0x2
>  
> -static void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
> +void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
>  {
>  	struct f2fs_xattr_header *header;
>  	void *txattr_addr;
> diff --git a/fsck/xattr.h b/fsck/xattr.h
> index b414629..beed3bb 100644
> --- a/fsck/xattr.h
> +++ b/fsck/xattr.h
> @@ -31,10 +31,62 @@ struct f2fs_xattr_entry {
>  	char e_name[0];		/* attribute name */
>  };
>  
> +#define FS_KEY_DESCRIPTOR_SIZE 8
> +#define FS_KEY_DERIVATION_NONCE_SIZE 16
> +
> +struct fscrypt_context {
> +	u8 format;
> +	u8 contents_encryption_mode;
> +	u8 filenames_encryption_mode;
> +	u8 flags;
> +	u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
> +	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
> +} __attribute__((packed));
> +
> +#define F2FS_ACL_VERSION	0x0001
> +
> +struct f2fs_acl_entry {
> +	__le16 e_tag;
> +	__le16 e_perm;
> +	__le32 e_id;
> +};
> +
> +struct f2fs_acl_entry_short {
> +	__le16 e_tag;
> +	__le16 e_perm;
> +};
> +
> +struct f2fs_acl_header {
> +	__le32 a_version;
> +};
> +
> +static inline int f2fs_acl_count(int size)
> +{
> +	ssize_t s;
> +	size -= sizeof(struct f2fs_acl_header);
> +	s = size - 4 * sizeof(struct f2fs_acl_entry_short);
> +	if (s < 0) {
> +		if (size % sizeof(struct f2fs_acl_entry_short))
> +			return -1;
> +		return size / sizeof(struct f2fs_acl_entry_short);
> +	} else {
> +		if (s % sizeof(struct f2fs_acl_entry))
> +			return -1;
> +		return s / sizeof(struct f2fs_acl_entry) + 4;
> +	}
> +}
> +
>  #define XATTR_ROUND	(3)
>  
>  #define XATTR_SELINUX_SUFFIX "selinux"
> -#define F2FS_XATTR_INDEX_SECURITY	6
> +#define F2FS_XATTR_INDEX_USER			1
> +#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS	2
> +#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT	3
> +#define F2FS_XATTR_INDEX_TRUSTED		4
> +#define F2FS_XATTR_INDEX_LUSTRE			5
> +#define F2FS_XATTR_INDEX_SECURITY		6
> +#define F2FS_XATTR_INDEX_ENCRYPTION		9
> +
>  #define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
>  
>  #define XATTR_HDR(ptr)		((struct f2fs_xattr_header *)(ptr))
> -- 
> 2.11.0

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2017-11-03 18:24 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-02  3:56 [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 1/9] fsck.f2fs: do not set fix_on directly Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 2/9] fsck.f2fs: do not fix corrupted nat entries in build_nat_area_bitmap Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 3/9] dump/fsck: introduce print_xattr_entry Sheng Yong
2017-11-03  3:27   ` Jaegeuk Kim
2017-11-03  4:08     ` [PATCH v3] " Sheng Yong
2017-11-03  4:14       ` [PATCH v4] " Sheng Yong
2017-11-03  4:25       ` [PATCH v5] " Sheng Yong
2017-11-03 18:24         ` Jaegeuk Kim
2017-11-02  3:56 ` [RFC PATCH v2 4/9] dump.f2fs: introduce dump_xattr Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 5/9] dump.f2fs: do not dump encrypted files Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 6/9] fsck.f2fs: introduce new option --dry-run Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 7/9] fsck.f2fs: introduce sanity_check_inode Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 8/9] f2fs-tools: remove unused list.h Sheng Yong
2017-11-02  3:56 ` [RFC PATCH v2 9/9] fsck.f2fs: format output message of FIX_MSG Sheng Yong
2017-11-02 15:08 ` [RFC PATCH v2 0/9] f2fs-tools: fix fix_on usage and introduce dump/print xattr Chao Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.