diff options
author | Chao Yu <yuchao0@huawei.com> | 2019-02-19 03:23:53 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2019-03-12 21:59:17 -0400 |
commit | aa2c8c43e4a5c242f5b0331c8b7a941b85f9435a (patch) | |
tree | 770a3dd298dc739d2b3b1aecdfd21316d54d8993 /fs/f2fs/super.c | |
parent | bc73a4b2414f2914fa895747166312b1527a97bb (diff) |
f2fs: fix to retry fill_super only if recovery failed
With current retry mechanism in f2fs_fill_super, first fill_super
fails due to no memory, then second fill_super runs w/o recovery,
if we succeed, we may lose fsynced data, it doesn't make sense.
Let's retry fill_super only if it occurs non-ENOMEM error during
recovery.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/super.c')
-rw-r--r-- | fs/f2fs/super.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 230845221c74..45121190a2ba 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -3053,10 +3053,11 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
3053 | struct f2fs_super_block *raw_super; | 3053 | struct f2fs_super_block *raw_super; |
3054 | struct inode *root; | 3054 | struct inode *root; |
3055 | int err; | 3055 | int err; |
3056 | bool retry = true, need_fsck = false; | 3056 | bool skip_recovery = false, need_fsck = false; |
3057 | char *options = NULL; | 3057 | char *options = NULL; |
3058 | int recovery, i, valid_super_block; | 3058 | int recovery, i, valid_super_block; |
3059 | struct curseg_info *seg_i; | 3059 | struct curseg_info *seg_i; |
3060 | int retry_cnt = 1; | ||
3060 | 3061 | ||
3061 | try_onemore: | 3062 | try_onemore: |
3062 | err = -EINVAL; | 3063 | err = -EINVAL; |
@@ -3345,7 +3346,7 @@ try_onemore: | |||
3345 | goto free_meta; | 3346 | goto free_meta; |
3346 | 3347 | ||
3347 | if (unlikely(is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))) | 3348 | if (unlikely(is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))) |
3348 | goto skip_recovery; | 3349 | goto reset_checkpoint; |
3349 | 3350 | ||
3350 | /* recover fsynced data */ | 3351 | /* recover fsynced data */ |
3351 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { | 3352 | if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { |
@@ -3362,11 +3363,13 @@ try_onemore: | |||
3362 | if (need_fsck) | 3363 | if (need_fsck) |
3363 | set_sbi_flag(sbi, SBI_NEED_FSCK); | 3364 | set_sbi_flag(sbi, SBI_NEED_FSCK); |
3364 | 3365 | ||
3365 | if (!retry) | 3366 | if (skip_recovery) |
3366 | goto skip_recovery; | 3367 | goto reset_checkpoint; |
3367 | 3368 | ||
3368 | err = f2fs_recover_fsync_data(sbi, false); | 3369 | err = f2fs_recover_fsync_data(sbi, false); |
3369 | if (err < 0) { | 3370 | if (err < 0) { |
3371 | if (err != -ENOMEM) | ||
3372 | skip_recovery = true; | ||
3370 | need_fsck = true; | 3373 | need_fsck = true; |
3371 | f2fs_msg(sb, KERN_ERR, | 3374 | f2fs_msg(sb, KERN_ERR, |
3372 | "Cannot recover all fsync data errno=%d", err); | 3375 | "Cannot recover all fsync data errno=%d", err); |
@@ -3382,7 +3385,7 @@ try_onemore: | |||
3382 | goto free_meta; | 3385 | goto free_meta; |
3383 | } | 3386 | } |
3384 | } | 3387 | } |
3385 | skip_recovery: | 3388 | reset_checkpoint: |
3386 | /* f2fs_recover_fsync_data() cleared this already */ | 3389 | /* f2fs_recover_fsync_data() cleared this already */ |
3387 | clear_sbi_flag(sbi, SBI_POR_DOING); | 3390 | clear_sbi_flag(sbi, SBI_POR_DOING); |
3388 | 3391 | ||
@@ -3428,7 +3431,7 @@ skip_recovery: | |||
3428 | sync_free_meta: | 3431 | sync_free_meta: |
3429 | /* safe to flush all the data */ | 3432 | /* safe to flush all the data */ |
3430 | sync_filesystem(sbi->sb); | 3433 | sync_filesystem(sbi->sb); |
3431 | retry = false; | 3434 | retry_cnt = 0; |
3432 | 3435 | ||
3433 | free_meta: | 3436 | free_meta: |
3434 | #ifdef CONFIG_QUOTA | 3437 | #ifdef CONFIG_QUOTA |
@@ -3488,8 +3491,8 @@ free_sbi: | |||
3488 | kvfree(sbi); | 3491 | kvfree(sbi); |
3489 | 3492 | ||
3490 | /* give only one another chance */ | 3493 | /* give only one another chance */ |
3491 | if (retry) { | 3494 | if (retry_cnt > 0 && skip_recovery) { |
3492 | retry = false; | 3495 | retry_cnt--; |
3493 | shrink_dcache_sb(sb); | 3496 | shrink_dcache_sb(sb); |
3494 | goto try_onemore; | 3497 | goto try_onemore; |
3495 | } | 3498 | } |