Skip to content

Commit d0b9e42

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: introduce inmem curseg
Previous implementation of aligned pinfile allocation will: - allocate new segment on cold data log no matter whether last used segment is partially used or not, it makes IOs more random; - force concurrent cold data/GCed IO going into warm data area, it can make a bad effect on hot/cold data separation; In this patch, we introduce a new type of log named 'inmem curseg', the differents from normal curseg is: - it reuses existed segment type (CURSEG_XXX_NODE/DATA); - it only exists in memory, its segno, blkofs, summary will not b persisted into checkpoint area; With this new feature, we can enhance scalability of log, special allocators can be created for purposes: - pure lfs allocator for aligned pinfile allocation or file defragmentation - pure ssr allocator for later feature So that, let's update aligned pinfile allocation to use this new inmem curseg fwk. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 376207a commit d0b9e42

File tree

8 files changed

+113
-52
lines changed

8 files changed

+113
-52
lines changed

fs/f2fs/checkpoint.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1619,11 +1619,16 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
16191619

16201620
f2fs_flush_sit_entries(sbi, cpc);
16211621

1622+
/* save inmem log status */
1623+
f2fs_save_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
1624+
16221625
err = do_checkpoint(sbi, cpc);
16231626
if (err)
16241627
f2fs_release_discard_addrs(sbi);
16251628
else
16261629
f2fs_clear_prefree_segments(sbi, cpc);
1630+
1631+
f2fs_restore_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
16271632
stop:
16281633
unblock_operations(sbi);
16291634
stat_inc_cp_count(sbi->stat_info);
@@ -1654,7 +1659,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
16541659
}
16551660

16561661
sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
1657-
NR_CURSEG_TYPE - __cp_payload(sbi)) *
1662+
NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
16581663
F2FS_ORPHANS_PER_BLOCK;
16591664
}
16601665

fs/f2fs/debug.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
164164
* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
165165
/ 2;
166166
si->util_invalid = 50 - si->util_free - si->util_valid;
167-
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
167+
for (i = CURSEG_HOT_DATA; i < NO_CHECK_TYPE; i++) {
168168
struct curseg_info *curseg = CURSEG_I(sbi, i);
169169
si->curseg[i] = curseg->segno;
170170
si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno);
@@ -393,6 +393,10 @@ static int stat_show(struct seq_file *s, void *v)
393393
si->dirty_seg[CURSEG_COLD_NODE],
394394
si->full_seg[CURSEG_COLD_NODE],
395395
si->valid_blks[CURSEG_COLD_NODE]);
396+
seq_printf(s, " - Pinned file: %8d %8d %8d\n",
397+
si->curseg[CURSEG_COLD_DATA_PINNED],
398+
si->cursec[CURSEG_COLD_DATA_PINNED],
399+
si->curzone[CURSEG_COLD_DATA_PINNED]);
396400
seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
397401
si->main_area_segs - si->dirty_count -
398402
si->prefree_count - si->free_segs,

fs/f2fs/f2fs.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,9 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
973973
*/
974974
#define NR_CURSEG_DATA_TYPE (3)
975975
#define NR_CURSEG_NODE_TYPE (3)
976-
#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
976+
#define NR_CURSEG_INMEM_TYPE (1)
977+
#define NR_CURSEG_PERSIST_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
978+
#define NR_CURSEG_TYPE (NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
977979

978980
enum {
979981
CURSEG_HOT_DATA = 0, /* directory entry blocks */
@@ -982,8 +984,10 @@ enum {
982984
CURSEG_HOT_NODE, /* direct node blocks of directory files */
983985
CURSEG_WARM_NODE, /* direct node blocks of normal files */
984986
CURSEG_COLD_NODE, /* indirect node blocks */
985-
NO_CHECK_TYPE,
986-
CURSEG_COLD_DATA_PINNED,/* cold data for pinned file */
987+
NR_PERSISTENT_LOG, /* number of persistent log */
988+
CURSEG_COLD_DATA_PINNED = NR_PERSISTENT_LOG,
989+
/* pinned file that needs consecutive block address */
990+
NO_CHECK_TYPE, /* number of persistent & inmem log */
987991
};
988992

989993
struct flush_cmd {
@@ -3333,6 +3337,8 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
33333337
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
33343338
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
33353339
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
3340+
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type);
3341+
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type);
33363342
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
33373343
unsigned int start, unsigned int end);
33383344
void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);

fs/f2fs/file.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,13 +1656,14 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
16561656
}
16571657

16581658
down_write(&sbi->pin_sem);
1659-
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
16601659

16611660
f2fs_lock_op(sbi);
1662-
f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA);
1661+
f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED);
16631662
f2fs_unlock_op(sbi);
16641663

1664+
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
16651665
err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);
1666+
16661667
up_write(&sbi->pin_sem);
16671668

16681669
done += map.m_len;

fs/f2fs/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
14631463
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
14641464

14651465
/* Move out cursegs from the target range */
1466-
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_TYPE; type++)
1466+
for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++)
14671467
f2fs_allocate_segment_for_resize(sbi, type, start, end);
14681468

14691469
/* do GC to move out valid blocks in the range */

fs/f2fs/segment.c

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,7 +1962,7 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
19621962

19631963
mutex_lock(&dirty_i->seglist_lock);
19641964
for_each_set_bit(segno, dirty_i->dirty_segmap[PRE], MAIN_SEGS(sbi))
1965-
__set_test_and_free(sbi, segno);
1965+
__set_test_and_free(sbi, segno, false);
19661966
mutex_unlock(&dirty_i->seglist_lock);
19671967
}
19681968

@@ -2500,31 +2500,39 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
25002500
struct curseg_info *curseg = CURSEG_I(sbi, type);
25012501
struct summary_footer *sum_footer;
25022502

2503+
curseg->inited = true;
25032504
curseg->segno = curseg->next_segno;
25042505
curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
25052506
curseg->next_blkoff = 0;
25062507
curseg->next_segno = NULL_SEGNO;
25072508

25082509
sum_footer = &(curseg->sum_blk->footer);
25092510
memset(sum_footer, 0, sizeof(struct summary_footer));
2510-
if (IS_DATASEG(type))
2511+
if (IS_DATASEG(curseg->seg_type))
25112512
SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
2512-
if (IS_NODESEG(type))
2513+
if (IS_NODESEG(curseg->seg_type))
25132514
SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
2514-
__set_sit_entry_type(sbi, type, curseg->segno, modified);
2515+
__set_sit_entry_type(sbi, curseg->seg_type, curseg->segno, modified);
25152516
}
25162517

25172518
static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
25182519
{
2520+
struct curseg_info *curseg = CURSEG_I(sbi, type);
2521+
25192522
/* if segs_per_sec is large than 1, we need to keep original policy. */
25202523
if (__is_large_section(sbi))
2521-
return CURSEG_I(sbi, type)->segno;
2524+
return curseg->segno;
2525+
2526+
/* inmem log may not locate on any segment after mount */
2527+
if (!curseg->inited)
2528+
return 0;
25222529

25232530
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
25242531
return 0;
25252532

25262533
if (test_opt(sbi, NOHEAP) &&
2527-
(type == CURSEG_HOT_DATA || IS_NODESEG(type)))
2534+
(curseg->seg_type == CURSEG_HOT_DATA ||
2535+
IS_NODESEG(curseg->seg_type)))
25282536
return 0;
25292537

25302538
if (SIT_I(sbi)->last_victim[ALLOC_NEXT])
@@ -2534,7 +2542,7 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
25342542
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)
25352543
return 0;
25362544

2537-
return CURSEG_I(sbi, type)->segno;
2545+
return curseg->segno;
25382546
}
25392547

25402548
/*
@@ -2544,12 +2552,14 @@ static unsigned int __get_next_segno(struct f2fs_sb_info *sbi, int type)
25442552
static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
25452553
{
25462554
struct curseg_info *curseg = CURSEG_I(sbi, type);
2555+
unsigned short seg_type = curseg->seg_type;
25472556
unsigned int segno = curseg->segno;
25482557
int dir = ALLOC_LEFT;
25492558

2550-
write_sum_page(sbi, curseg->sum_blk,
2559+
if (curseg->inited)
2560+
write_sum_page(sbi, curseg->sum_blk,
25512561
GET_SUM_BLOCK(sbi, segno));
2552-
if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
2562+
if (seg_type == CURSEG_WARM_DATA || seg_type == CURSEG_COLD_DATA)
25532563
dir = ALLOC_RIGHT;
25542564

25552565
if (test_opt(sbi, NOHEAP))
@@ -2626,6 +2636,43 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
26262636
f2fs_put_page(sum_page, 1);
26272637
}
26282638

2639+
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type)
2640+
{
2641+
struct curseg_info *curseg = CURSEG_I(sbi, type);
2642+
2643+
mutex_lock(&curseg->curseg_mutex);
2644+
if (!curseg->inited)
2645+
goto out;
2646+
2647+
if (get_valid_blocks(sbi, curseg->segno, false)) {
2648+
write_sum_page(sbi, curseg->sum_blk,
2649+
GET_SUM_BLOCK(sbi, curseg->segno));
2650+
} else {
2651+
mutex_lock(&DIRTY_I(sbi)->seglist_lock);
2652+
__set_test_and_free(sbi, curseg->segno, true);
2653+
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
2654+
}
2655+
out:
2656+
mutex_unlock(&curseg->curseg_mutex);
2657+
}
2658+
2659+
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type)
2660+
{
2661+
struct curseg_info *curseg = CURSEG_I(sbi, type);
2662+
2663+
mutex_lock(&curseg->curseg_mutex);
2664+
if (!curseg->inited)
2665+
goto out;
2666+
if (get_valid_blocks(sbi, curseg->segno, false))
2667+
goto out;
2668+
2669+
mutex_lock(&DIRTY_I(sbi)->seglist_lock);
2670+
__set_test_and_inuse(sbi, curseg->segno);
2671+
mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
2672+
out:
2673+
mutex_unlock(&curseg->curseg_mutex);
2674+
}
2675+
26292676
static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
26302677
{
26312678
struct curseg_info *curseg = CURSEG_I(sbi, type);
@@ -2742,11 +2789,15 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type)
27422789
struct curseg_info *curseg = CURSEG_I(sbi, type);
27432790
unsigned int old_segno;
27442791

2792+
if (!curseg->inited)
2793+
goto alloc;
2794+
27452795
if (!curseg->next_blkoff &&
27462796
!get_valid_blocks(sbi, curseg->segno, false) &&
27472797
!get_ckpt_valid_blocks(sbi, curseg->segno))
27482798
return;
27492799

2800+
alloc:
27502801
old_segno = curseg->segno;
27512802
SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true);
27522803
locate_dirty_segment(sbi, old_segno);
@@ -3130,19 +3181,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
31303181
{
31313182
struct sit_info *sit_i = SIT_I(sbi);
31323183
struct curseg_info *curseg = CURSEG_I(sbi, type);
3133-
bool put_pin_sem = false;
3134-
3135-
if (type == CURSEG_COLD_DATA) {
3136-
/* GC during CURSEG_COLD_DATA_PINNED allocation */
3137-
if (down_read_trylock(&sbi->pin_sem)) {
3138-
put_pin_sem = true;
3139-
} else {
3140-
type = CURSEG_WARM_DATA;
3141-
curseg = CURSEG_I(sbi, type);
3142-
}
3143-
} else if (type == CURSEG_COLD_DATA_PINNED) {
3144-
type = CURSEG_COLD_DATA;
3145-
}
31463184

31473185
down_read(&SM_I(sbi)->curseg_lock);
31483186

@@ -3208,9 +3246,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
32083246
mutex_unlock(&curseg->curseg_mutex);
32093247

32103248
up_read(&SM_I(sbi)->curseg_lock);
3211-
3212-
if (put_pin_sem)
3213-
up_read(&sbi->pin_sem);
32143249
}
32153250

32163251
static void update_device_state(struct f2fs_io_info *fio)
@@ -3578,7 +3613,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
35783613
blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
35793614
CURSEG_HOT_DATA]);
35803615
if (__exist_node_summaries(sbi))
3581-
blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
3616+
blk_addr = sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type);
35823617
else
35833618
blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
35843619
} else {
@@ -3656,8 +3691,9 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
36563691
}
36573692

36583693
if (__exist_node_summaries(sbi))
3659-
f2fs_ra_meta_pages(sbi, sum_blk_addr(sbi, NR_CURSEG_TYPE, type),
3660-
NR_CURSEG_TYPE - type, META_CP, true);
3694+
f2fs_ra_meta_pages(sbi,
3695+
sum_blk_addr(sbi, NR_CURSEG_PERSIST_TYPE, type),
3696+
NR_CURSEG_PERSIST_TYPE - type, META_CP, true);
36613697

36623698
for (; type <= CURSEG_COLD_NODE; type++) {
36633699
err = read_normal_summaries(sbi, type);
@@ -4159,14 +4195,14 @@ static int build_curseg(struct f2fs_sb_info *sbi)
41594195
struct curseg_info *array;
41604196
int i;
41614197

4162-
array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE, sizeof(*array)),
4163-
GFP_KERNEL);
4198+
array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE,
4199+
sizeof(*array)), GFP_KERNEL);
41644200
if (!array)
41654201
return -ENOMEM;
41664202

41674203
SM_I(sbi)->curseg_array = array;
41684204

4169-
for (i = 0; i < NR_CURSEG_TYPE; i++) {
4205+
for (i = 0; i < NO_CHECK_TYPE; i++) {
41704206
mutex_init(&array[i].curseg_mutex);
41714207
array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL);
41724208
if (!array[i].sum_blk)
@@ -4176,8 +4212,13 @@ static int build_curseg(struct f2fs_sb_info *sbi)
41764212
sizeof(struct f2fs_journal), GFP_KERNEL);
41774213
if (!array[i].journal)
41784214
return -ENOMEM;
4215+
if (i < NR_PERSISTENT_LOG)
4216+
array[i].seg_type = CURSEG_HOT_DATA + i;
4217+
else if (i == CURSEG_COLD_DATA_PINNED)
4218+
array[i].seg_type = CURSEG_COLD_DATA;
41794219
array[i].segno = NULL_SEGNO;
41804220
array[i].next_blkoff = 0;
4221+
array[i].inited = false;
41814222
}
41824223
return restore_curseg_summaries(sbi);
41834224
}
@@ -4416,7 +4457,7 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
44164457
* In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
44174458
* In LFS curseg, all blkaddr after .next_blkoff should be unused.
44184459
*/
4419-
for (i = 0; i < NO_CHECK_TYPE; i++) {
4460+
for (i = 0; i < NR_PERSISTENT_LOG; i++) {
44204461
struct curseg_info *curseg = CURSEG_I(sbi, i);
44214462
struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
44224463
unsigned int blkofs = curseg->next_blkoff;
@@ -4645,7 +4686,7 @@ int f2fs_fix_curseg_write_pointer(struct f2fs_sb_info *sbi)
46454686
{
46464687
int i, ret;
46474688

4648-
for (i = 0; i < NO_CHECK_TYPE; i++) {
4689+
for (i = 0; i < NR_PERSISTENT_LOG; i++) {
46494690
ret = fix_curseg_write_pointer(sbi, i);
46504691
if (ret)
46514692
return ret;

0 commit comments

Comments
 (0)