@@ -3492,32 +3492,6 @@ static void destroy_fsync_dnodes(struct list_head *head)
del_fsync_inode(entry);
}
-static int find_node_blk_fast(struct f2fs_sb_info *sbi, block_t *blkaddr_fast,
- struct f2fs_node *node_blk_fast, bool *is_detecting)
-{
- int i, err;
-
- for (i = 0; i < 2; i++) {
- if (!f2fs_is_valid_blkaddr(sbi, *blkaddr_fast, META_POR)) {
- *is_detecting = false;
- return 0;
- }
-
- err = dev_read_block(node_blk_fast, *blkaddr_fast);
- if (err)
- return err;
-
- if (!is_recoverable_dnode(sbi, node_blk_fast)) {
- *is_detecting = false;
- return 0;
- }
-
- *blkaddr_fast = next_blkaddr_of_node(node_blk_fast);
- }
-
- return 0;
-}
-
static int loop_node_chain_fix(block_t blkaddr_fast,
struct f2fs_node *node_blk_fast,
block_t blkaddr, struct f2fs_node *node_blk)
@@ -3560,6 +3534,58 @@ static int loop_node_chain_fix(block_t blkaddr_fast,
return err;
}
+/* Detect looped node chain with Floyd's cycle detection algorithm. */
+static int sanity_check_node_chain(struct f2fs_sb_info *sbi,
+ block_t *blkaddr_fast, struct f2fs_node *node_blk_fast,
+ block_t blkaddr, struct f2fs_node *node_blk,
+ bool *is_detecting)
+{
+ int i, err;
+
+ if (!*is_detecting)
+ return 0;
+
+ for (i = 0; i < 2; i++) {
+ if (!f2fs_is_valid_blkaddr(sbi, *blkaddr_fast, META_POR)) {
+ *is_detecting = false;
+ return 0;
+ }
+
+ err = dev_read_block(node_blk_fast, *blkaddr_fast);
+ if (err)
+ return err;
+
+ if (!is_recoverable_dnode(sbi, node_blk_fast)) {
+ *is_detecting = false;
+ return 0;
+ }
+
+ *blkaddr_fast = next_blkaddr_of_node(node_blk_fast);
+ }
+
+ if (*blkaddr_fast != blkaddr)
+ return 0;
+
+ ASSERT_MSG("\tdetect looped node chain, blkaddr:%u\n", blkaddr);
+ if (!c.fix_on)
+ return -1;
+
+ err = loop_node_chain_fix(NEXT_FREE_BLKADDR(sbi,
+ CURSEG_I(sbi, CURSEG_WARM_NODE)),
+ node_blk_fast, blkaddr, node_blk);
+ if (err)
+ return err;
+
+ /* Since we call get_fsync_inode() to ensure there are no
+ * duplicate inodes in the inode_list even if there are
+ * duplicate blkaddr, we can continue running after fixing the
+ * looped node chain.
+ */
+ *is_detecting = false;
+
+ return 0;
+}
+
static int find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
{
struct curseg_info *curseg;
@@ -3608,42 +3634,11 @@ static int find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head)
next:
blkaddr = next_blkaddr_of_node(node_blk);
- /* Below we will detect looped node chain with Floyd's cycle
- * detection algorithm.
- */
- if (!is_detecting)
- continue;
-
- err = find_node_blk_fast(sbi, &blkaddr_fast,
- node_blk_fast, &is_detecting);
+ err = sanity_check_node_chain(sbi, &blkaddr_fast,
+ node_blk_fast, blkaddr, node_blk,
+ &is_detecting);
if (err)
break;
-
- if (!is_detecting)
- continue;
-
- if (blkaddr_fast != blkaddr)
- continue;
-
- ASSERT_MSG("\tdetect looped node chain, blkaddr:%u\n",
- blkaddr);
-
- if (!c.fix_on) {
- err = -1;
- break;
- }
-
- err = loop_node_chain_fix(NEXT_FREE_BLKADDR(sbi, curseg),
- node_blk_fast, blkaddr, node_blk);
- if (err)
- break;
-
- /* Since we call get_fsync_inode() to ensure there are no
- * duplicate inodes in the inode_list even if there are
- * duplicate blkaddr, we can continue running after fixing the
- * looped node chain.
- */
- is_detecting = false;
}
free(node_blk_fast);
Refactor looped node chain detected logic for cleanup as kernel does. Suggested-by: Chao Yu <chao@kernel.org> Signed-off-by: Chunhai Guo <guochunhai@vivo.com> --- fsck/mount.c | 115 ++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 60 deletions(-)