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]> --- fsck/mount.c | 24 ++++++++++++++++++++++++ fsck/node.h | 14 ++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/fsck/mount.c b/fsck/mount.c index f03fa2d..07b8e6e 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -3881,6 +3881,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; @@ -3897,6 +3898,29 @@ int f2fs_find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head) entry = get_fsync_inode(head, ino_of_node(node_blk)); if (!entry) { + if (IS_INODE(node_blk) && is_dent_dnode(node_blk)) { + get_nat_entry(sbi, ino_of_node(node_blk), &nat_entry); + if (nat_entry.block_addr != NULL_ADDR) { + if (!c.fix_on) + ASSERT_MSG("ino: %u is_dent:%d nat entry blkaddr is %#X\n", + ino_of_node(node_blk), is_dent_dnode(node_blk), + nat_entry.block_addr); + else if (f2fs_dev_is_writable()) { + int ret = 0; + + ASSERT_MSG("Set node_blk %#x fsync flag [%u] -> [0]" + " next_blkaddr [%#x] -> [NULL_ADDR]\n", + blkaddr, is_fsync_dnode(node_blk), + F2FS_NODE_FOOTER(node_blk)->next_blkaddr); + F2FS_NODE_FOOTER(node_blk)->next_blkaddr = NULL_ADDR; + set_fsync_mark(node_blk, 0); + ret = dev_write_block(node_blk, blkaddr, + f2fs_io_type_to_rw_hint(CURSEG_WARM_NODE)); + ASSERT(ret >= 0); + goto next; + } + } + } entry = add_fsync_inode(head, ino_of_node(node_blk)); if (!entry) { err = -1; diff --git a/fsck/node.h b/fsck/node.h index 19f1e57..7c16cc8 100644 --- a/fsck/node.h +++ b/fsck/node.h @@ -173,6 +173,20 @@ 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 set_fsync_mark(page, mark) set_mark(page, mark, FSYNC_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
