When sudden f2fs shutdown happens on zoned block devices, write pointers can be inconsistent with valid blocks counts in meta data. The failure scenario is as follows:
- Just before a sudden shutdown, a new segment in a new zone is selected for a current segment. Write commands were executed to the segment. and the zone has a write pointer not at zone start. - Before the write commands complete, shutdown happens. Meta data is not updated and still keeps zero valid blocks count for the zone. - After next mount of the file system, the zone is selected for the next write target because it has zero valid blocks count. However, it has the write pointer not at zone start. Then "Unaligned write command" error happens. To avoid this potential error path, reset write pointers if the zone does not have a current segment, the write pointer is not at the zone start and the zone has no valid blocks. Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawas...@wdc.com> --- fsck/fsck.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 21a06ac..cc9bbc0 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -2595,6 +2595,7 @@ static int fsck_chk_write_pointer(int i, struct blk_zone *blkz, void *opaque) int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT; unsigned int segs_per_zone = sbi->segs_per_sec * sbi->secs_per_zone; void *zero_blk; + block_t zone_valid_blocks = 0; if (blk_zone_conv(blkz)) return 0; @@ -2615,8 +2616,35 @@ static int fsck_chk_write_pointer(int i, struct blk_zone *blkz, void *opaque) break; } - if (cs_index >= NR_CURSEG_TYPE) + if (cs_index >= NR_CURSEG_TYPE) { + for (b = zone_block; b < zone_block + c.zone_blocks && + IS_VALID_BLK_ADDR(sbi, b); b += c.blks_per_seg) { + se = get_seg_entry(sbi, GET_SEGNO(sbi, b)); + zone_valid_blocks += se->valid_blocks; + } + if (wp_block == zone_block || zone_valid_blocks) + return 0; + + /* + * The write pointer is not at zone start but there is no valid + * block in the zone. Segments in the zone can be selected for + * next write. Need to reset the write pointer to avoid + * unaligned write command error. + */ + if (c.fix_on) { + FIX_MSG("Reset write pointer at segment 0x%x", + zone_segno); + ret = f2fs_reset_zone(dev, blkz); + if (ret) + return ret; + fsck->chk.wp_fixed_zones++; + } else { + MSG(0, "Inconsistent write pointer at segment 0x%x\n", + zone_segno); + fsck->chk.wp_inconsistent_zones++; + } return 0; + } /* check write pointer consistency with the curseg in the zone */ cs_block = START_BLOCK(sbi, cs->segno) + cs->next_blkoff; -- 2.21.0 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel