linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH] fsck.f2fs: lookup and relink root inode
@ 2019-12-31 10:05 Chao Yu
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2019-12-31 10:05 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel

As Stephanos reported in mailing list:

Info: checkpoint state = 1 :  unmount
[ASSERT] (sanity_check_nid: 362)  --> nid[0x3] ino is 0

The root cause is root inode's nat entry is corrupted, this patch
add logic to search root inode from all node blocks, try to relink
root inode's nat to target node block.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/main.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 145 insertions(+), 1 deletion(-)

diff --git a/fsck/main.c b/fsck/main.c
index cd4ca20..5bcbf39 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -614,12 +614,152 @@ void f2fs_parse_options(int argc, char *argv[])
 	error_out(prog);
 }
 
+bool is_root_nat_corrupted(struct f2fs_sb_info *sbi)
+{
+	struct node_info ni;
+	struct f2fs_node *node_blk = NULL;
+	nid_t root_ino = sbi->root_ino_num;
+
+	node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk != NULL);
+
+	if (!IS_VALID_NID(sbi, root_ino)) {
+		ASSERT_MSG("nid is not valid. [0x%x]", root_ino);
+		goto out;
+	}
+
+	get_node_info(sbi, root_ino, &ni);
+	if (ni.ino == 0) {
+		ASSERT_MSG("nid[0x%x] ino is 0", root_ino);
+		goto out;
+	}
+
+	if (ni.blk_addr == NEW_ADDR) {
+		ASSERT_MSG("nid is NEW_ADDR. [0x%x]", root_ino);
+		goto out;
+	}
+
+	if (ni.blk_addr == NULL_ADDR) {
+		ASSERT_MSG("nid is NULL_ADDR. [0x%x]", root_ino);
+		goto out;
+	}
+
+	if (!IS_VALID_BLK_ADDR(sbi, ni.blk_addr)) {
+		ASSERT_MSG("blkaddress is not valid. [0x%x]", ni.blk_addr);
+		goto out;
+	}
+	free(node_blk);
+	return 0;
+out:
+	free(node_blk);
+	return -EINVAL;
+}
+
+static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr)
+{
+	struct seg_entry *se;
+	u32 offset;
+
+	se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr));
+	offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+	return f2fs_test_bit(offset,
+			(const char *)se->cur_valid_map) != 0;
+}
+
+int fsck_find_and_link_root(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_node *node_blk;
+	int segment_count = SM_I(sbi)->main_segments;
+	int segno;
+	bool valid_bitmap = true;
+	block_t last_blkaddr = NULL_ADDR;
+	u64 last_ctime = 0;
+	u32 last_ctime_nsec = 0;
+	int ret = -EINVAL;
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk);
+
+retry:
+	for (segno = 0; segno < segment_count; segno++) {
+		struct seg_entry *se = get_seg_entry(sbi, segno);
+		block_t blkaddr = START_BLOCK(sbi, segno);
+		int ret;
+		int i;
+
+		if (IS_DATASEG(se->type))
+			continue;
+
+		dev_readahead(blkaddr << F2FS_BLKSIZE_BITS,
+				sbi->blocks_per_seg << F2FS_BLKSIZE_BITS);
+
+		for (i = 0; i < sbi->blocks_per_seg; i++, blkaddr++) {
+			if (valid_bitmap && !is_sit_bitmap_set(sbi, blkaddr))
+				continue;
+			if (!valid_bitmap && is_sit_bitmap_set(sbi, blkaddr))
+				continue;
+			ret = dev_read_block(node_blk, blkaddr);
+			ASSERT(ret >= 0);
+
+			if (node_blk->footer.ino == sbi->root_ino_num &&
+				node_blk->footer.nid == sbi->root_ino_num)
+				break;
+		}
+
+		if (i != sbi->blocks_per_seg) {
+			if (valid_bitmap) {
+				if (c.fix_on) {
+					FIX_MSG("Relink root inode, blkaddr: 0x%x",
+						blkaddr);
+					update_nat_blkaddr(sbi, sbi->root_ino_num,
+							sbi->root_ino_num, blkaddr);
+					ret = 0;
+				}
+				goto out;
+			} else {
+				if (last_blkaddr == NULL_ADDR)
+					goto init;
+				if (le64_to_cpu(node_blk->i.i_ctime) <
+					last_ctime)
+					continue;
+				if (le64_to_cpu(node_blk->i.i_ctime) ==
+					last_ctime &&
+					le32_to_cpu(node_blk->i.i_ctime_nsec) <=
+					last_ctime_nsec)
+					continue;
+init:
+				last_blkaddr = blkaddr;
+				last_ctime =
+					le64_to_cpu(node_blk->i.i_ctime);
+				last_ctime_nsec =
+					le32_to_cpu(node_blk->i.i_ctime_nsec);
+			}
+		}
+	}
+
+	if (valid_bitmap) {
+		valid_bitmap = false;
+		goto retry;
+	} else {
+		if (last_blkaddr && c.fix_on) {
+			FIX_MSG("Relink root inode, blkaddr: 0x%x", last_blkaddr);
+			update_nat_blkaddr(sbi, sbi->root_ino_num,
+					sbi->root_ino_num, last_blkaddr);
+			ret = 0;
+		}
+	}
+out:
+	free(node_blk);
+	return ret;
+}
+
 static void do_fsck(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
 	u32 flag = le32_to_cpu(ckpt->ckpt_flags);
 	u32 blk_cnt;
-	errcode_t ret;
+	errcode_t ret = 0;
 
 	fsck_init(sbi);
 
@@ -675,6 +815,10 @@ static void do_fsck(struct f2fs_sb_info *sbi)
 		}
 	}
 	fsck_chk_orphan_node(sbi);
+
+	if (is_root_nat_corrupted(sbi))
+		fsck_find_and_link_root(sbi);
+
 	fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num,
 			F2FS_FT_DIR, TYPE_INODE, &blk_cnt, NULL);
 	fsck_chk_quota_files(sbi);
-- 
2.18.0.rc1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

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

* [f2fs-dev] [PATCH] fsck.f2fs: lookup and relink root inode
@ 2020-04-07 10:03 Chao Yu
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2020-04-07 10:03 UTC (permalink / raw)
  To: linux-f2fs-devel; +Cc: kilobyte, jaegeuk

As Stephanos reported in mailing list:

Info: checkpoint state = 1 :  unmount
[ASSERT] (sanity_check_nid: 362)  --> nid[0x3] ino is 0

The root cause is root inode's nat entry is corrupted, this patch
add logic to search root inode from all node blocks, try to relink
root inode's nat to target node block.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/fsck.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fsck/fsck.h |   1 +
 2 files changed, 136 insertions(+)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 0389146..e22ed4a 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -572,6 +572,141 @@ err:
 	return -EINVAL;
 }
 
+static int is_root_nat_corrupted(struct f2fs_sb_info *sbi)
+{
+	struct node_info ni;
+	struct f2fs_node *node_blk = NULL;
+	int ret;
+
+	node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk != NULL);
+
+	ret = sanity_check_nid(sbi, sbi->root_ino_num, node_blk,
+					F2FS_FT_DIR, TYPE_INODE, &ni);
+
+	free(node_blk);
+	return ret;
+}
+
+static bool is_sit_bitmap_set(struct f2fs_sb_info *sbi, u32 blk_addr)
+{
+	struct seg_entry *se;
+	u32 offset;
+
+	se = get_seg_entry(sbi, GET_SEGNO(sbi, blk_addr));
+	offset = OFFSET_IN_SEG(sbi, blk_addr);
+
+	return f2fs_test_bit(offset,
+			(const char *)se->cur_valid_map) != 0;
+}
+
+int fsck_find_and_link_root(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_node *node_blk;
+	int segment_count = SM_I(sbi)->main_segments;
+	int segno;
+	bool valid_bitmap = true;
+	block_t last_blkaddr = NULL_ADDR;
+	u64 last_ctime = 0;
+	u32 last_ctime_nsec = 0;
+	int ret = -EINVAL;
+
+	if (!is_root_nat_corrupted(sbi))
+		return 0;
+
+	node_blk = calloc(BLOCK_SZ, 1);
+	ASSERT(node_blk);
+
+	printf("fsck_find_and_link_root\n");
+
+retry:
+	for (segno = 0; segno < segment_count; segno++) {
+		struct seg_entry *se = get_seg_entry(sbi, segno);
+		block_t blkaddr = START_BLOCK(sbi, segno);
+		int ret;
+		int i;
+
+		if (IS_DATASEG(se->type))
+			continue;
+
+		dev_readahead(blkaddr << F2FS_BLKSIZE_BITS,
+				sbi->blocks_per_seg << F2FS_BLKSIZE_BITS);
+
+		for (i = 0; i < sbi->blocks_per_seg; i++, blkaddr++) {
+			if (valid_bitmap && !is_sit_bitmap_set(sbi, blkaddr))
+				continue;
+			if (!valid_bitmap && is_sit_bitmap_set(sbi, blkaddr))
+				continue;
+			ret = dev_read_block(node_blk, blkaddr);
+			ASSERT(ret >= 0);
+
+			if (le32_to_cpu(node_blk->footer.ino) !=
+					sbi->root_ino_num ||
+				le32_to_cpu(node_blk->footer.nid) !=
+					sbi->root_ino_num)
+				continue;
+
+			if (!IS_INODE(node_blk))
+				continue;
+
+			if (le32_to_cpu(node_blk->i.i_generation) ||
+					le32_to_cpu(node_blk->i.i_namelen))
+				continue;
+
+			printf("possible valid_bitmap: %d, nid: %u, blkaddr:%u\n",
+				valid_bitmap,
+				le32_to_cpu(node_blk->footer.nid),
+				blkaddr);
+			break;
+		}
+
+		if (i != sbi->blocks_per_seg) {
+			if (valid_bitmap) {
+				if (c.fix_on) {
+					FIX_MSG("Relink root inode, blkaddr: 0x%x",
+						blkaddr);
+					update_nat_blkaddr(sbi, sbi->root_ino_num,
+							sbi->root_ino_num, blkaddr);
+					ret = 0;
+				}
+				goto out;
+			} else {
+				if (last_blkaddr == NULL_ADDR)
+					goto init;
+				if (le64_to_cpu(node_blk->i.i_ctime) <
+					last_ctime)
+					continue;
+				if (le64_to_cpu(node_blk->i.i_ctime) ==
+					last_ctime &&
+					le32_to_cpu(node_blk->i.i_ctime_nsec) <=
+					last_ctime_nsec)
+					continue;
+init:
+				last_blkaddr = blkaddr;
+				last_ctime =
+					le64_to_cpu(node_blk->i.i_ctime);
+				last_ctime_nsec =
+					le32_to_cpu(node_blk->i.i_ctime_nsec);
+			}
+		}
+	}
+
+	if (valid_bitmap) {
+		valid_bitmap = false;
+		goto retry;
+	} else {
+		if (last_blkaddr && c.fix_on) {
+			FIX_MSG("Relink root inode, blkaddr: 0x%x", last_blkaddr);
+			update_nat_blkaddr(sbi, sbi->root_ino_num,
+					sbi->root_ino_num, last_blkaddr);
+			ret = 0;
+		}
+	}
+out:
+	free(node_blk);
+	return ret;
+}
+
 static inline void get_extent_info(struct extent_info *ext,
 					struct f2fs_extent *i_ext)
 {
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 2de6f62..4ce51d7 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -150,6 +150,7 @@ extern int fsck_sanity_check_nid(struct f2fs_sb_info *, u32,
 extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
 		enum FILE_TYPE, enum NODE_TYPE, u32 *,
 		struct child_info *);
+extern int fsck_find_and_link_root(struct f2fs_sb_info *);
 extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
 		struct f2fs_node *, u32 *, struct node_info *, struct child_info *);
 extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
-- 
2.18.0.rc1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

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

end of thread, other threads:[~2020-04-07 10:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-31 10:05 [f2fs-dev] [PATCH] fsck.f2fs: lookup and relink root inode Chao Yu
2020-04-07 10:03 Chao Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).