Came across a dead loop in recovery like this: ...... [ 24.680480s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597696 [ 24.698394s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597697 [ 24.724334s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724334s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724365s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724365s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724365s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724395s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724395s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724395s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724395s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 [ 24.724426s][pid:320,cpu0,init]find_fsync_dnodes: blkaddr =13597698 ......
Mount process will block in dead loop and fsck can do nothing with this error, This patch abandon recovery if node chain is cyclical. Signed-off-by: Yunlei He <[email protected]> --- fs/f2fs/recovery.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index cbeef73..318243c 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -221,11 +221,11 @@ static void recover_inode(struct inode *inode, struct page *page) } static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, - bool check_only) + bool check_only, block_t *looped_blkaddr) { struct curseg_info *curseg; struct page *page = NULL; - block_t blkaddr; + block_t blkaddr, last_blkaddr; int err = 0; /* get node pages in the current segment */ @@ -239,6 +239,17 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, return 0; page = get_tmp_page(sbi, blkaddr); + if (PageChecked(page)) { + f2fs_msg(sbi->sb, KERN_ERR, "Abandon looped node block list"); + *looped_blkaddr = last_blkaddr; + break; + } + + /* + * it's not needed to clear PG_checked flag in temp page since we + * will truncate all those pages in the end of recovery. + */ + SetPageChecked(page); if (!is_recoverable_dnode(page)) break; @@ -279,6 +290,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head, entry->last_dentry = blkaddr; next: /* check next segment */ + last_blkaddr = blkaddr; blkaddr = next_blkaddr_of_node(page); f2fs_put_page(page, 1); @@ -525,7 +537,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, } static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, - struct list_head *dir_list) + struct list_head *dir_list, block_t looped_blkaddr) { struct curseg_info *curseg; struct page *page = NULL; @@ -577,6 +589,10 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, if (entry->blkaddr == blkaddr) del_fsync_inode(entry); next: + /* in case of looped node chain */ + if (blkaddr == looped_blkaddr) + break; + /* check next segment */ blkaddr = next_blkaddr_of_node(page); f2fs_put_page(page, 1); @@ -596,6 +612,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) bool need_writecp = false; #ifdef CONFIG_QUOTA int quota_enabled; + block_t looped_blkaddr = 0; #endif if (s_flags & SB_RDONLY) { @@ -624,7 +641,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) mutex_lock(&sbi->cp_mutex); /* step #1: find fsynced inode numbers */ - err = find_fsync_dnodes(sbi, &inode_list, check_only); + err = find_fsync_dnodes(sbi, &inode_list, check_only, &looped_blkaddr); if (err || list_empty(&inode_list)) goto skip; @@ -636,7 +653,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) need_writecp = true; /* step #2: recover data */ - err = recover_data(sbi, &inode_list, &dir_list); + err = recover_data(sbi, &inode_list, &dir_list, looped_blkaddr); if (!err) f2fs_bug_on(sbi, !list_empty(&inode_list)); skip: -- 1.9.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
