mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 13:22:57 +00:00
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: Daeho Jeong <daehojeong@google.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
6f560c0f2a
commit
9f792ab8e3
1 changed files with 55 additions and 35 deletions
|
@ -4910,22 +4910,31 @@ static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
|
|||
}
|
||||
|
||||
/*
|
||||
* The write pointer matches with the valid blocks or
|
||||
* already points to the end of the zone.
|
||||
* When safely unmounted in the previous mount, we can trust write
|
||||
* pointers. Otherwise, finish zones.
|
||||
*/
|
||||
if ((last_valid_block + 1 == wp_block) ||
|
||||
(zone->wp == zone->start + zone->len))
|
||||
return 0;
|
||||
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.
|
||||
*/
|
||||
if ((last_valid_block + 1 == wp_block) ||
|
||||
(zone->wp == zone->start + zone->len))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (last_valid_block + 1 == zone_block) {
|
||||
/*
|
||||
* 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);
|
||||
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.
|
||||
*/
|
||||
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 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]",
|
||||
GET_SEGNO(sbi, last_valid_block),
|
||||
GET_BLKOFF_FROM_SEG0(sbi, last_valid_block),
|
||||
wp_segno, wp_blkoff);
|
||||
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.
|
||||
*/
|
||||
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,18 +5031,27 @@ static int fix_curseg_write_pointer(struct f2fs_sb_info *sbi, int type)
|
|||
if (zone.type != BLK_ZONE_TYPE_SEQWRITE_REQ)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
wp_sector_off = zone.wp & GENMASK(log_sectors_per_block - 1, 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);
|
||||
wp_sector_off = zone.wp & GENMASK(log_sectors_per_block - 1, 0);
|
||||
|
||||
if (cs->segno == wp_segno && cs->next_blkoff == wp_blkoff &&
|
||||
wp_sector_off == 0)
|
||||
return 0;
|
||||
if (cs->segno == wp_segno && cs->next_blkoff == wp_blkoff &&
|
||||
wp_sector_off == 0)
|
||||
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);
|
||||
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);
|
||||
} 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);
|
||||
|
|
Loading…
Reference in a new issue