Snap for 6670641 from 75ec64039d6af9b04906b018c67342a6d2a09f1c to rvc-qpr1-release

Change-Id: Iab3e9fedaba0d22917ac28d0cceb80c99b95dbd1
diff --git a/fsck/f2fs.h b/fsck/f2fs.h
index 2a00d35..76e8272 100644
--- a/fsck/f2fs.h
+++ b/fsck/f2fs.h
@@ -273,6 +273,9 @@
 	u32 free_segments;
 
 	int cp_backuped;			/* backup valid checkpoint */
+
+	/* true if late_build_segment_manger() is called */
+	bool seg_manager_done;
 };
 
 static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
diff --git a/fsck/mount.c b/fsck/mount.c
index fb45941..6d467c8 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -1288,15 +1288,14 @@
 	return block_addr;
 }
 
-static int f2fs_init_nid_bitmap(struct f2fs_sb_info *sbi)
+/* will not init nid_bitmap from nat */
+static int f2fs_early_init_nid_bitmap(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_nm_info *nm_i = NM_I(sbi);
 	int nid_bitmap_size = (nm_i->max_nid + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
 	struct f2fs_summary_block *sum = curseg->sum_blk;
 	struct f2fs_journal *journal = &sum->journal;
-	struct f2fs_nat_block *nat_block;
-	block_t start_blk;
 	nid_t nid;
 	int i;
 
@@ -1310,28 +1309,6 @@
 	/* arbitrarily set 0 bit */
 	f2fs_set_bit(0, nm_i->nid_bitmap);
 
-	nat_block = malloc(F2FS_BLKSIZE);
-	if (!nat_block) {
-		free(nm_i->nid_bitmap);
-		return -ENOMEM;
-	}
-
-	f2fs_ra_meta_pages(sbi, 0, NAT_BLOCK_OFFSET(nm_i->max_nid),
-							META_NAT);
-
-	for (nid = 0; nid < nm_i->max_nid; nid++) {
-		if (!(nid % NAT_ENTRY_PER_BLOCK)) {
-			int ret;
-
-			start_blk = current_nat_addr(sbi, nid, NULL);
-			ret = dev_read_block(nat_block, start_blk);
-			ASSERT(ret >= 0);
-		}
-
-		if (nat_block->entries[nid % NAT_ENTRY_PER_BLOCK].block_addr)
-			f2fs_set_bit(nid, nm_i->nid_bitmap);
-	}
-
 	if (nats_in_cursum(journal) > NAT_JOURNAL_ENTRIES) {
 		MSG(0, "\tError: f2fs_init_nid_bitmap truncate n_nats(%u) to "
 			"NAT_JOURNAL_ENTRIES(%lu)\n",
@@ -1361,6 +1338,41 @@
 		if (addr != NULL_ADDR)
 			f2fs_set_bit(nid, nm_i->nid_bitmap);
 	}
+	return 0;
+}
+
+/* will init nid_bitmap from nat */
+static int f2fs_late_init_nid_bitmap(struct f2fs_sb_info *sbi)
+{
+	struct f2fs_nm_info *nm_i = NM_I(sbi);
+	struct f2fs_nat_block *nat_block;
+	block_t start_blk;
+	nid_t nid;
+
+	if (!(c.func == SLOAD || c.func == FSCK))
+		return 0;
+
+	nat_block = malloc(F2FS_BLKSIZE);
+	if (!nat_block) {
+		free(nm_i->nid_bitmap);
+		return -ENOMEM;
+	}
+
+	f2fs_ra_meta_pages(sbi, 0, NAT_BLOCK_OFFSET(nm_i->max_nid),
+							META_NAT);
+	for (nid = 0; nid < nm_i->max_nid; nid++) {
+		if (!(nid % NAT_ENTRY_PER_BLOCK)) {
+			int ret;
+
+			start_blk = current_nat_addr(sbi, nid, NULL);
+			ret = dev_read_block(nat_block, start_blk);
+			ASSERT(ret >= 0);
+		}
+
+		if (nat_block->entries[nid % NAT_ENTRY_PER_BLOCK].block_addr)
+			f2fs_set_bit(nid, nm_i->nid_bitmap);
+	}
+
 	free(nat_block);
 	return 0;
 }
@@ -1565,7 +1577,7 @@
 
 	/* copy version bitmap */
 	memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
-	return f2fs_init_nid_bitmap(sbi);
+	return f2fs_early_init_nid_bitmap(sbi);
 }
 
 int build_node_manager(struct f2fs_sb_info *sbi)
@@ -2272,7 +2284,7 @@
 	return 0;
 }
 
-static int build_segment_manager(struct f2fs_sb_info *sbi)
+static int early_build_segment_manager(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
 	struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
@@ -2294,7 +2306,7 @@
 	sm_info->main_segments = get_sb(segment_count_main);
 	sm_info->ssa_blkaddr = get_sb(ssa_blkaddr);
 
-	if (build_sit_info(sbi) || build_curseg(sbi) || build_sit_entries(sbi)) {
+	if (build_sit_info(sbi) || build_curseg(sbi)) {
 		free(sm_info);
 		return -ENOMEM;
 	}
@@ -2302,6 +2314,20 @@
 	return 0;
 }
 
+static int late_build_segment_manager(struct f2fs_sb_info *sbi)
+{
+	if (sbi->seg_manager_done)
+		return 1; /* this function was already called */
+
+	sbi->seg_manager_done = true;
+	if (build_sit_entries(sbi)) {
+		free (sbi->sm_info);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 void build_sit_area_bitmap(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
@@ -3375,6 +3401,12 @@
 	if (ret)
 		goto out;
 
+	ret = late_build_segment_manager(sbi);
+	if (ret < 0) {
+		ERR_MSG("late_build_segment_manager failed\n");
+		goto out;
+	}
+
 	ret = traverse_dnodes(sbi, &inode_list);
 out:
 	destroy_fsync_dnodes(&inode_list);
@@ -3445,8 +3477,8 @@
 	sbi->last_valid_block_count = sbi->total_valid_block_count;
 	sbi->alloc_valid_block_count = 0;
 
-	if (build_segment_manager(sbi)) {
-		ERR_MSG("build_segment_manager failed\n");
+	if (early_build_segment_manager(sbi)) {
+		ERR_MSG("early_build_segment_manager failed\n");
 		return -1;
 	}
 
@@ -3463,6 +3495,16 @@
 	if (!f2fs_should_proceed(sb, get_cp(ckpt_flags)))
 		return 1;
 
+	if (late_build_segment_manager(sbi) < 0) {
+		ERR_MSG("late_build_segment_manager failed\n");
+		return -1;
+	}
+
+	if (f2fs_late_init_nid_bitmap(sbi)) {
+		ERR_MSG("f2fs_late_init_nid_bitmap failed\n");
+		return -1;
+	}
+
 	/* Check nat_bits */
 	if (c.func == FSCK && is_set_ckpt_flags(cp, CP_NAT_BITS_FLAG)) {
 		if (check_nat_bits(sbi, sb, cp) && c.fix_on)