mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
synced 2024-11-23 17:53:39 +08:00
fsck.f2fs: allow fsck to fix issues with online resize due to SPO
Add support for new CP flag CP_RESIZEFS_FLAG set during online resize FS. If SPO happens after SB is updated but CP isn't, then allow fsck to fix it. The fsck errors without this fix - Info: CKPT version = 6ed7bccb Wrong user_block_count(2233856) [f2fs_do_mount:3365] Checkpoint is polluted The subsequent mount failure without this fix - [ 11.294650] F2FS-fs (sda8): Wrong user_block_count: 2233856 [ 11.300272] F2FS-fs (sda8): Failed to get valid F2FS checkpoint Signed-off-by: Sahitya Tummala <stummala@codeaurora.org> Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
11e4322127
commit
9a31cefa29
70
fsck/mount.c
70
fsck/mount.c
@ -429,6 +429,8 @@ void print_cp_state(u32 flag)
|
||||
MSG(0, "%s", " orphan_inodes");
|
||||
if (flag & CP_DISABLED_FLAG)
|
||||
MSG(0, "%s", " disabled");
|
||||
if (flag & CP_RESIZEFS_FLAG)
|
||||
MSG(0, "%s", " resizefs");
|
||||
if (flag & CP_UMOUNT_FLAG)
|
||||
MSG(0, "%s", " unmount");
|
||||
else
|
||||
@ -1123,11 +1125,31 @@ fail_no_cp:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a return value of 1, caller should further check for c.fix_on state
|
||||
* and take appropriate action.
|
||||
*/
|
||||
static int f2fs_should_proceed(struct f2fs_super_block *sb, u32 flag)
|
||||
{
|
||||
if (!c.fix_on && (c.auto_fix || c.preen_mode)) {
|
||||
if (flag & CP_FSCK_FLAG ||
|
||||
flag & CP_QUOTA_NEED_FSCK_FLAG ||
|
||||
(exist_qf_ino(sb) && (flag & CP_ERROR_FLAG))) {
|
||||
c.fix_on = 1;
|
||||
} else if (!c.preen_mode) {
|
||||
print_cp_state(flag);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
unsigned int total, fsmeta;
|
||||
struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
|
||||
struct f2fs_checkpoint *cp = F2FS_CKPT(sbi);
|
||||
unsigned int flag = get_cp(ckpt_flags);
|
||||
unsigned int ovp_segments, reserved_segments;
|
||||
unsigned int main_segs, blocks_per_seg;
|
||||
unsigned int sit_segs, nat_segs;
|
||||
@ -1164,8 +1186,34 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
||||
log_blocks_per_seg = get_sb(log_blocks_per_seg);
|
||||
if (!user_block_count || user_block_count >=
|
||||
segment_count_main << log_blocks_per_seg) {
|
||||
MSG(0, "\tWrong user_block_count(%u)\n", user_block_count);
|
||||
return 1;
|
||||
ASSERT_MSG("\tWrong user_block_count(%u)\n", user_block_count);
|
||||
|
||||
if (!f2fs_should_proceed(sb, flag))
|
||||
return 1;
|
||||
if (!c.fix_on)
|
||||
return 1;
|
||||
|
||||
if (flag & (CP_FSCK_FLAG | CP_RESIZEFS_FLAG)) {
|
||||
u32 valid_user_block_cnt;
|
||||
u32 seg_cnt_main = get_sb(segment_count) -
|
||||
(get_sb(segment_count_ckpt) +
|
||||
get_sb(segment_count_sit) +
|
||||
get_sb(segment_count_nat) +
|
||||
get_sb(segment_count_ssa));
|
||||
|
||||
/* validate segment_count_main in sb first */
|
||||
if (seg_cnt_main != get_sb(segment_count_main)) {
|
||||
MSG(0, "Inconsistent segment_cnt_main %u in sb\n",
|
||||
segment_count_main << log_blocks_per_seg);
|
||||
return 1;
|
||||
}
|
||||
valid_user_block_cnt = ((get_sb(segment_count_main) -
|
||||
get_cp(overprov_segment_count)) * c.blks_per_seg);
|
||||
MSG(0, "Info: Fix wrong user_block_count in CP: (%u) -> (%u)\n",
|
||||
user_block_count, valid_user_block_cnt);
|
||||
set_cp(user_block_count, valid_user_block_cnt);
|
||||
c.bug_on = 1;
|
||||
}
|
||||
}
|
||||
|
||||
main_segs = get_sb(segment_count_main);
|
||||
@ -3355,6 +3403,8 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
|
||||
return -1;
|
||||
}
|
||||
|
||||
c.bug_on = 0;
|
||||
|
||||
if (sanity_check_ckpt(sbi)) {
|
||||
ERR_MSG("Checkpoint is polluted\n");
|
||||
return -1;
|
||||
@ -3374,8 +3424,6 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
|
||||
c.fix_on = 1;
|
||||
}
|
||||
|
||||
c.bug_on = 0;
|
||||
|
||||
if (tune_sb_features(sbi))
|
||||
return -1;
|
||||
|
||||
@ -3405,18 +3453,8 @@ int f2fs_do_mount(struct f2fs_sb_info *sbi)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c.fix_on && (c.auto_fix || c.preen_mode)) {
|
||||
u32 flag = get_cp(ckpt_flags);
|
||||
|
||||
if (flag & CP_FSCK_FLAG ||
|
||||
flag & CP_QUOTA_NEED_FSCK_FLAG ||
|
||||
(exist_qf_ino(sb) && (flag & CP_ERROR_FLAG))) {
|
||||
c.fix_on = 1;
|
||||
} else if (!c.preen_mode) {
|
||||
print_cp_state(flag);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!f2fs_should_proceed(sb, get_cp(ckpt_flags)))
|
||||
return 1;
|
||||
|
||||
/* Check nat_bits */
|
||||
if (c.func == FSCK && is_set_ckpt_flags(cp, CP_NAT_BITS_FLAG)) {
|
||||
|
@ -678,6 +678,7 @@ struct f2fs_super_block {
|
||||
/*
|
||||
* For checkpoint
|
||||
*/
|
||||
#define CP_RESIZEFS_FLAG 0x00004000
|
||||
#define CP_DISABLED_FLAG 0x00001000
|
||||
#define CP_QUOTA_NEED_FSCK_FLAG 0x00000800
|
||||
#define CP_LARGE_NAT_BITMAP_FLAG 0x00000400
|
||||
|
Loading…
Reference in New Issue
Block a user