Skip to content

Commit deecd28

Browse files
yohanjoungJaegeuk Kim
authored andcommitted
f2fs: add ckpt_valid_blocks to the section entry
when performing buffered writes in a large section, overhead is incurred due to the iteration through ckpt_valid_blocks within the section. when SEGS_PER_SEC is 128, this overhead accounts for 20% within the f2fs_write_single_data_page routine. as the size of the section increases, the overhead also grows. to handle this problem ckpt_valid_blocks is added within the section entries. Test insmod null_blk.ko nr_devices=1 completion_nsec=1 submit_queues=8 hw_queue_depth=64 max_sectors=512 bs=4096 memory_backed=1 make_f2fs /dev/block/nullb0 make_f2fs -s 128 /dev/block/nullb0 fio --bs=512k --size=1536M --rw=write --name=1 --filename=/mnt/test_dir/seq_write --ioengine=io_uring --iodepth=64 --end_fsync=1 before SEGS_PER_SEC 1 2556MiB/s SEGS_PER_SEC 128 2145MiB/s after SEGS_PER_SEC 1 2556MiB/s SEGS_PER_SEC 128 2556MiB/s Signed-off-by: yohan.joung <yohan.joung@sk.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 249ad43 commit deecd28

File tree

2 files changed

+85
-18
lines changed

2 files changed

+85
-18
lines changed

fs/f2fs/segment.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,7 +2447,7 @@ static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr,
24472447
* that the consecutive input blocks belong to the same segment.
24482448
*/
24492449
static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_entry *se,
2450-
block_t blkaddr, unsigned int offset, int del)
2450+
unsigned int segno, block_t blkaddr, unsigned int offset, int del)
24512451
{
24522452
bool exist;
24532453
#ifdef CONFIG_F2FS_CHECK_FS
@@ -2492,15 +2492,21 @@ static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_ent
24922492
f2fs_test_and_clear_bit(offset + i, se->discard_map))
24932493
sbi->discard_blks++;
24942494

2495-
if (!f2fs_test_bit(offset + i, se->ckpt_valid_map))
2495+
if (!f2fs_test_bit(offset + i, se->ckpt_valid_map)) {
24962496
se->ckpt_valid_blocks -= 1;
2497+
if (__is_large_section(sbi))
2498+
get_sec_entry(sbi, segno)->ckpt_valid_blocks -= 1;
2499+
}
24972500
}
24982501

2502+
if (__is_large_section(sbi))
2503+
sanity_check_valid_blocks(sbi, segno);
2504+
24992505
return del;
25002506
}
25012507

25022508
static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry *se,
2503-
block_t blkaddr, unsigned int offset, int del)
2509+
unsigned int segno, block_t blkaddr, unsigned int offset, int del)
25042510
{
25052511
bool exist;
25062512
#ifdef CONFIG_F2FS_CHECK_FS
@@ -2533,12 +2539,21 @@ static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry
25332539
* or newly invalidated.
25342540
*/
25352541
if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
2536-
if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map))
2542+
if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map)) {
25372543
se->ckpt_valid_blocks++;
2544+
if (__is_large_section(sbi))
2545+
get_sec_entry(sbi, segno)->ckpt_valid_blocks++;
2546+
}
25382547
}
25392548

2540-
if (!f2fs_test_bit(offset, se->ckpt_valid_map))
2549+
if (!f2fs_test_bit(offset, se->ckpt_valid_map)) {
25412550
se->ckpt_valid_blocks += del;
2551+
if (__is_large_section(sbi))
2552+
get_sec_entry(sbi, segno)->ckpt_valid_blocks += del;
2553+
}
2554+
2555+
if (__is_large_section(sbi))
2556+
sanity_check_valid_blocks(sbi, segno);
25422557

25432558
return del;
25442559
}
@@ -2569,9 +2584,9 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
25692584

25702585
/* Update valid block bitmap */
25712586
if (del > 0) {
2572-
del = update_sit_entry_for_alloc(sbi, se, blkaddr, offset, del);
2587+
del = update_sit_entry_for_alloc(sbi, se, segno, blkaddr, offset, del);
25732588
} else {
2574-
del = update_sit_entry_for_release(sbi, se, blkaddr, offset, del);
2589+
del = update_sit_entry_for_release(sbi, se, segno, blkaddr, offset, del);
25752590
}
25762591

25772592
__mark_sit_entry_dirty(sbi, segno);
@@ -4708,6 +4723,12 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
47084723
&raw_sit->entries[sit_offset]);
47094724
}
47104725

4726+
/* update ckpt_valid_block */
4727+
if (__is_large_section(sbi)) {
4728+
set_ckpt_valid_blocks(sbi, segno);
4729+
sanity_check_valid_blocks(sbi, segno);
4730+
}
4731+
47114732
__clear_bit(segno, bitmap);
47124733
sit_i->dirty_sentries--;
47134734
ses->entry_cnt--;
@@ -5029,6 +5050,16 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
50295050
}
50305051
up_read(&curseg->journal_rwsem);
50315052

5053+
/* update ckpt_valid_block */
5054+
if (__is_large_section(sbi)) {
5055+
unsigned int segno;
5056+
5057+
for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
5058+
set_ckpt_valid_blocks(sbi, segno);
5059+
sanity_check_valid_blocks(sbi, segno);
5060+
}
5061+
}
5062+
50325063
if (err)
50335064
return err;
50345065

fs/f2fs/segment.h

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ struct seg_entry {
211211

212212
struct sec_entry {
213213
unsigned int valid_blocks; /* # of valid blocks in a section */
214+
unsigned int ckpt_valid_blocks; /* # of valid blocks last cp in a section */
214215
};
215216

216217
#define MAX_SKIP_GC_COUNT 16
@@ -347,22 +348,57 @@ static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
347348
static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
348349
unsigned int segno, bool use_section)
349350
{
350-
if (use_section && __is_large_section(sbi)) {
351-
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
352-
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
353-
unsigned int blocks = 0;
354-
int i;
351+
if (use_section && __is_large_section(sbi))
352+
return get_sec_entry(sbi, segno)->ckpt_valid_blocks;
353+
else
354+
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
355+
}
355356

356-
for (i = 0; i < SEGS_PER_SEC(sbi); i++, start_segno++) {
357-
struct seg_entry *se = get_seg_entry(sbi, start_segno);
357+
static inline void set_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
358+
unsigned int segno)
359+
{
360+
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
361+
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
362+
unsigned int blocks = 0;
363+
int i;
358364

359-
blocks += se->ckpt_valid_blocks;
360-
}
361-
return blocks;
365+
for (i = 0; i < SEGS_PER_SEC(sbi); i++, start_segno++) {
366+
struct seg_entry *se = get_seg_entry(sbi, start_segno);
367+
368+
blocks += se->ckpt_valid_blocks;
362369
}
363-
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
370+
get_sec_entry(sbi, segno)->ckpt_valid_blocks = blocks;
364371
}
365372

373+
#ifdef CONFIG_F2FS_CHECK_FS
374+
static inline void sanity_check_valid_blocks(struct f2fs_sb_info *sbi,
375+
unsigned int segno)
376+
{
377+
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
378+
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
379+
unsigned int blocks = 0;
380+
int i;
381+
382+
for (i = 0; i < SEGS_PER_SEC(sbi); i++, start_segno++) {
383+
struct seg_entry *se = get_seg_entry(sbi, start_segno);
384+
385+
blocks += se->ckpt_valid_blocks;
386+
}
387+
388+
if (blocks != get_sec_entry(sbi, segno)->ckpt_valid_blocks) {
389+
f2fs_err(sbi,
390+
"Inconsistent ckpt valid blocks: "
391+
"seg entry(%d) vs sec entry(%d) at secno %d",
392+
blocks, get_sec_entry(sbi, segno)->ckpt_valid_blocks, secno);
393+
f2fs_bug_on(sbi, 1);
394+
}
395+
}
396+
#else
397+
static inline void sanity_check_valid_blocks(struct f2fs_sb_info *sbi,
398+
unsigned int segno)
399+
{
400+
}
401+
#endif
366402
static inline void seg_info_from_raw_sit(struct seg_entry *se,
367403
struct f2fs_sit_entry *rs)
368404
{

0 commit comments

Comments
 (0)