From: liujinbao1 <[email protected]> During SPO tests, when mounting F2FS, an -EINVAL error was returned. The issue originates from the f2fs_recover_inode_page function's check, where old_ni.blk_addr != NULL_ADDR under the conditions of IS_INODE(folio) && is_dent_dnode(folio). Add detection and repair for this scenario in fsck.
Signed-off-by: Sheng Yong <[email protected]> Signed-off-by: Yongpeng Yang <[email protected]> Signed-off-by: Jinbao Liu <[email protected]> --- v2: - Clear the node_blk dent flag, proceed with recovery of this and subsequent data. --- v1: - Clear the node_blk fsync flag, set next_blkaddr=NULL, skip recovery of this and later data. --- fsck/mount.c | 21 ++++++++++++++++++++- fsck/node.h | 13 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/fsck/mount.c b/fsck/mount.c index 6f640a0..8254644 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -3878,6 +3878,7 @@ int f2fs_find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head) while (1) { struct fsync_inode_entry *entry; + struct f2fs_nat_entry nat_entry; if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) break; @@ -3902,8 +3903,26 @@ int f2fs_find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head) } entry->blkaddr = blkaddr; - if (IS_INODE(node_blk) && is_dent_dnode(node_blk)) + if (IS_INODE(node_blk) && is_dent_dnode(node_blk)) { + get_nat_entry(sbi, ino_of_node(node_blk), &nat_entry); + if (is_valid_data_blkaddr(nat_entry.block_addr)) { + ASSERT_MSG("Invalid dent flag: blkaddr = %#x, " + "ino: %u, is_dent:%d, nat entry blkaddr is %#X\n", + blkaddr, ino_of_node(node_blk), is_dent_dnode(node_blk), + nat_entry.block_addr); + if (c.fix_on && f2fs_dev_is_writable()) { + int ret = 0; + + FIX_MSG("Clear dent flag: blkaddr:%#x, ino: %u\n", + blkaddr, ino_of_node(node_blk)); + set_dentry_mark(node_blk, 0); + ret = update_inode(sbi, node_blk, blkaddr); + ASSERT(ret >= 0); + goto next; + } + } entry->last_dentry = blkaddr; + } next: blkaddr = next_blkaddr_of_node(node_blk); diff --git a/fsck/node.h b/fsck/node.h index 19f1e57..f3e2c46 100644 --- a/fsck/node.h +++ b/fsck/node.h @@ -173,6 +173,19 @@ static inline void set_cold_node(struct f2fs_node *rn, bool is_dir) F2FS_NODE_FOOTER(rn)->flag = cpu_to_le32(flag); } +static inline void set_mark(struct f2fs_node *rn, int mark, int type) +{ + unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(rn)->flag); + + if (mark) + flag |= (1 << type); + else + flag &= ~(1 << type); + F2FS_NODE_FOOTER(rn)->flag = cpu_to_le32(flag); +} + +#define set_dentry_mark(page, mark) set_mark(page, mark, DENT_BIT_SHIFT) + #define is_fsync_dnode(node_blk) is_node(node_blk, FSYNC_BIT_SHIFT) #define is_dent_dnode(node_blk) is_node(node_blk, DENT_BIT_SHIFT) -- 2.25.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
