Commit 9f792ab8 authored by Daeho Jeong's avatar Daeho Jeong Committed by Jaegeuk Kim
Browse files

f2fs: clean up zones when not successfully unmounted



We can't trust write pointers when the previous mount was not
successfully unmounted.

Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 6f560c0f
Loading
Loading
Loading
Loading
+56 −36
Original line number Diff line number Diff line
@@ -4909,6 +4909,11 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
			break;
	}

	/*
	 * When safely unmounted in the previous mount, we can trust write
	 * pointers. Otherwise, finish zones.
	 */
	if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
		/*
		 * The write pointer matches with the valid blocks or
		 * already points to the end of the zone.
@@ -4916,16 +4921,20 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
		if ((last_valid_block + 1 == wp_block) ||
				(zone->wp == zone->start + zone->len))
			return 0;
	}

	if (last_valid_block + 1 == zone_block) {
		if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
			/*
		 * If there is no valid block in the zone and if write pointer
		 * is not at zone start, reset the write pointer.
			 * If there is no valid block in the zone and if write
			 * pointer is not at zone start, reset the write
			 * pointer.
			 */
			f2fs_notice(sbi,
			      "Zone without valid block has non-zero write "
			      "pointer. Reset the write pointer: wp[0x%x,0x%x]",
			      wp_segno, wp_blkoff);
		}
		ret = __f2fs_issue_discard_zone(sbi, fdev->bdev, zone_block,
					zone->len >> log_sectors_per_block);
		if (ret)
@@ -4935,18 +4944,20 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
		return ret;
	}

	if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
		/*
	 * If there are valid blocks and the write pointer doesn't
	 * match with them, we need to report the inconsistency and
	 * fill the zone till the end to close the zone. This inconsistency
	 * does not cause write error because the zone will not be selected
	 * for write operation until it get discarded.
		 * If there are valid blocks and the write pointer doesn't match
		 * with them, we need to report the inconsistency and fill
		 * the zone till the end to close the zone. This inconsistency
		 * does not cause write error because the zone will not be
		 * selected for write operation until it get discarded.
		 */
	f2fs_notice(sbi, "Valid blocks are not aligned with write pointer: "
		    "valid block[0x%x,0x%x] wp[0x%x,0x%x]",
		f2fs_notice(sbi, "Valid blocks are not aligned with write "
			    "pointer: valid block[0x%x,0x%x] wp[0x%x,0x%x]",
			    GET_SEGNO(sbi, last_valid_block),
			    GET_BLKOFF_FROM_SEG0(sbi, last_valid_block),
			    wp_segno, wp_blkoff);
	}

	ret = blkdev_zone_mgmt(fdev->bdev, REQ_OP_ZONE_FINISH,
				zone->start, zone->len, GFP_NOFS);
@@ -5020,6 +5031,11 @@ static int fix_curseg_write_pointer(struct f2fs_sb_info *sbi, int type)
	if (zone.type != BLK_ZONE_TYPE_SEQWRITE_REQ)
		return 0;

	/*
	 * When safely unmounted in the previous mount, we could use current
	 * segments. Otherwise, allocate new sections.
	 */
	if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
		wp_block = zbd->start_blk + (zone.wp >> log_sectors_per_block);
		wp_segno = GET_SEGNO(sbi, wp_block);
		wp_blkoff = wp_block - START_BLOCK(sbi, wp_segno);
@@ -5030,8 +5046,12 @@ static int fix_curseg_write_pointer(struct f2fs_sb_info *sbi, int type)
			return 0;

		f2fs_notice(sbi, "Unaligned curseg[%d] with write pointer: "
		    "curseg[0x%x,0x%x] wp[0x%x,0x%x]",
		    type, cs->segno, cs->next_blkoff, wp_segno, wp_blkoff);
			    "curseg[0x%x,0x%x] wp[0x%x,0x%x]", type, cs->segno,
			    cs->next_blkoff, wp_segno, wp_blkoff);
	} else {
		f2fs_notice(sbi, "Not successfully unmounted in the previous "
			    "mount");
	}

	f2fs_notice(sbi, "Assign new section to curseg[%d]: "
		    "curseg[0x%x,0x%x]", type, cs->segno, cs->next_blkoff);