Skip to content

Commit 2459306

Browse files
Zhiguo NiuJaegeuk Kim
authored andcommitted
f2fs: fix to handle error paths of {new,change}_curseg()
{new,change}_curseg() may return error in some special cases, error handling should be did in their callers, and this will also facilitate subsequent error path expansion in {new,change}_curseg(). Signed-off-by: Zhiguo Niu <[email protected]> Signed-off-by: Chao Yu <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 31f85cc commit 2459306

File tree

4 files changed

+45
-27
lines changed

4 files changed

+45
-27
lines changed

fs/f2fs/f2fs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3700,10 +3700,10 @@ int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
37003700
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
37013701
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
37023702
bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
3703-
void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
3703+
int f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
37043704
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
37053705
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
3706-
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
3706+
int f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
37073707
unsigned int start, unsigned int end);
37083708
int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
37093709
int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi);

fs/f2fs/gc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,8 +2035,11 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
20352035
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
20362036

20372037
/* Move out cursegs from the target range */
2038-
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++)
2039-
f2fs_allocate_segment_for_resize(sbi, type, start, end);
2038+
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++) {
2039+
err = f2fs_allocate_segment_for_resize(sbi, type, start, end);
2040+
if (err)
2041+
goto out;
2042+
}
20402043

20412044
/* do GC to move out valid blocks in the range */
20422045
err = f2fs_gc_range(sbi, start, end, dry_run, 0);

fs/f2fs/segment.c

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2863,7 +2863,7 @@ bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
28632863
* This function always allocates a used segment(from dirty seglist) by SSR
28642864
* manner, so it should recover the existing segment information of valid blocks
28652865
*/
2866-
static void change_curseg(struct f2fs_sb_info *sbi, int type)
2866+
static int change_curseg(struct f2fs_sb_info *sbi, int type)
28672867
{
28682868
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
28692869
struct curseg_info *curseg = CURSEG_I(sbi, type);
@@ -2888,60 +2888,65 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
28882888
if (IS_ERR(sum_page)) {
28892889
/* GC won't be able to use stale summary pages by cp_error */
28902890
memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
2891-
return;
2891+
return PTR_ERR(sum_page);
28922892
}
28932893
sum_node = (struct f2fs_summary_block *)page_address(sum_page);
28942894
memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
28952895
f2fs_put_page(sum_page, 1);
2896+
return 0;
28962897
}
28972898

28982899
static int get_ssr_segment(struct f2fs_sb_info *sbi, int type,
28992900
int alloc_mode, unsigned long long age);
29002901

2901-
static void get_atssr_segment(struct f2fs_sb_info *sbi, int type,
2902+
static int get_atssr_segment(struct f2fs_sb_info *sbi, int type,
29022903
int target_type, int alloc_mode,
29032904
unsigned long long age)
29042905
{
29052906
struct curseg_info *curseg = CURSEG_I(sbi, type);
2907+
int ret = 0;
29062908

29072909
curseg->seg_type = target_type;
29082910

29092911
if (get_ssr_segment(sbi, type, alloc_mode, age)) {
29102912
struct seg_entry *se = get_seg_entry(sbi, curseg->next_segno);
29112913

29122914
curseg->seg_type = se->type;
2913-
change_curseg(sbi, type);
2915+
ret = change_curseg(sbi, type);
29142916
} else {
29152917
/* allocate cold segment by default */
29162918
curseg->seg_type = CURSEG_COLD_DATA;
2917-
new_curseg(sbi, type, true);
2919+
ret = new_curseg(sbi, type, true);
29182920
}
29192921
stat_inc_seg_type(sbi, curseg);
2922+
return ret;
29202923
}
29212924

2922-
static void __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
2925+
static int __f2fs_init_atgc_curseg(struct f2fs_sb_info *sbi)
29232926
{
29242927
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC);
2928+
int ret = 0;
29252929

29262930
if (!sbi->am.atgc_enabled)
2927-
return;
2931+
return 0;
29282932

29292933
f2fs_down_read(&SM_I(sbi)->curseg_lock);
29302934

29312935
mutex_lock(&curseg->curseg_mutex);
29322936
down_write(&SIT_I(sbi)->sentry_lock);
29332937

2934-
get_atssr_segment(sbi, CURSEG_ALL_DATA_ATGC, CURSEG_COLD_DATA, SSR, 0);
2938+
ret = get_atssr_segment(sbi, CURSEG_ALL_DATA_ATGC,
2939+
CURSEG_COLD_DATA, SSR, 0);
29352940

29362941
up_write(&SIT_I(sbi)->sentry_lock);
29372942
mutex_unlock(&curseg->curseg_mutex);
29382943

29392944
f2fs_up_read(&SM_I(sbi)->curseg_lock);
2940-
2945+
return ret;
29412946
}
2942-
void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi)
2947+
int f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi)
29432948
{
2944-
__f2fs_init_atgc_curseg(sbi);
2949+
return __f2fs_init_atgc_curseg(sbi);
29452950
}
29462951

29472952
static void __f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type)
@@ -3069,11 +3074,12 @@ static bool need_new_seg(struct f2fs_sb_info *sbi, int type)
30693074
return false;
30703075
}
30713076

3072-
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
3077+
int f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
30733078
unsigned int start, unsigned int end)
30743079
{
30753080
struct curseg_info *curseg = CURSEG_I(sbi, type);
30763081
unsigned int segno;
3082+
int ret = 0;
30773083

30783084
f2fs_down_read(&SM_I(sbi)->curseg_lock);
30793085
mutex_lock(&curseg->curseg_mutex);
@@ -3084,9 +3090,9 @@ void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
30843090
goto unlock;
30853091

30863092
if (f2fs_need_SSR(sbi) && get_ssr_segment(sbi, type, SSR, 0))
3087-
change_curseg(sbi, type);
3093+
ret = change_curseg(sbi, type);
30883094
else
3089-
new_curseg(sbi, type, true);
3095+
ret = new_curseg(sbi, type, true);
30903096

30913097
stat_inc_seg_type(sbi, curseg);
30923098

@@ -3100,6 +3106,7 @@ void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
31003106

31013107
mutex_unlock(&curseg->curseg_mutex);
31023108
f2fs_up_read(&SM_I(sbi)->curseg_lock);
3109+
return ret;
31033110
}
31043111

31053112
static int __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
@@ -3486,14 +3493,17 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
34863493
bool from_gc = (type == CURSEG_ALL_DATA_ATGC);
34873494
struct seg_entry *se = NULL;
34883495
bool segment_full = false;
3496+
int ret = 0;
34893497

34903498
f2fs_down_read(&SM_I(sbi)->curseg_lock);
34913499

34923500
mutex_lock(&curseg->curseg_mutex);
34933501
down_write(&sit_i->sentry_lock);
34943502

3495-
if (curseg->segno == NULL_SEGNO)
3503+
if (curseg->segno == NULL_SEGNO) {
3504+
ret = -ENOSPC;
34963505
goto out_err;
3506+
}
34973507

34983508
if (from_gc) {
34993509
f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO);
@@ -3546,17 +3556,17 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
35463556
}
35473557

35483558
if (from_gc) {
3549-
get_atssr_segment(sbi, type, se->type,
3559+
ret = get_atssr_segment(sbi, type, se->type,
35503560
AT_SSR, se->mtime);
35513561
} else {
35523562
if (need_new_seg(sbi, type))
3553-
new_curseg(sbi, type, false);
3563+
ret = new_curseg(sbi, type, false);
35543564
else
3555-
change_curseg(sbi, type);
3565+
ret = change_curseg(sbi, type);
35563566
stat_inc_seg_type(sbi, curseg);
35573567
}
35583568

3559-
if (curseg->segno == NULL_SEGNO)
3569+
if (ret)
35603570
goto out_err;
35613571
}
35623572

@@ -3599,7 +3609,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
35993609
up_write(&sit_i->sentry_lock);
36003610
mutex_unlock(&curseg->curseg_mutex);
36013611
f2fs_up_read(&SM_I(sbi)->curseg_lock);
3602-
return -ENOSPC;
3612+
return ret;
36033613

36043614
}
36053615

@@ -3828,7 +3838,8 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
38283838
/* change the current segment */
38293839
if (segno != curseg->segno) {
38303840
curseg->next_segno = segno;
3831-
change_curseg(sbi, type);
3841+
if (change_curseg(sbi, type))
3842+
goto out_unlock;
38323843
}
38333844

38343845
curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
@@ -3854,12 +3865,14 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
38543865
if (recover_curseg) {
38553866
if (old_cursegno != curseg->segno) {
38563867
curseg->next_segno = old_cursegno;
3857-
change_curseg(sbi, type);
3868+
if (change_curseg(sbi, type))
3869+
goto out_unlock;
38583870
}
38593871
curseg->next_blkoff = old_blkoff;
38603872
curseg->alloc_type = old_alloc_type;
38613873
}
38623874

3875+
out_unlock:
38633876
up_write(&sit_i->sentry_lock);
38643877
mutex_unlock(&curseg->curseg_mutex);
38653878
f2fs_up_write(&SM_I(sbi)->curseg_lock);

fs/f2fs/super.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4680,7 +4680,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
46804680
if (err)
46814681
goto free_meta;
46824682

4683-
f2fs_init_inmem_curseg(sbi);
4683+
err = f2fs_init_inmem_curseg(sbi);
4684+
if (err)
4685+
goto sync_free_meta;
46844686

46854687
/* f2fs_recover_fsync_data() cleared this already */
46864688
clear_sbi_flag(sbi, SBI_POR_DOING);

0 commit comments

Comments
 (0)