f2fs: introduce f2fs_get_section_mtime

When segs_per_sec is larger than 1, section may contain invalid segments,
mtime should be the average value of each valid blocks,
so introduce f2fs_get_section_mtime to
record the average mtime of all valid blocks in a section.

Signed-off-by: liuderong <liuderong@oppo.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
liuderong 2024-09-18 18:06:20 +08:00 committed by Jaegeuk Kim
parent eca631b8fe
commit b19ee72722
4 changed files with 38 additions and 18 deletions

View File

@ -3783,6 +3783,8 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi);
unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
unsigned int segno);
unsigned long long f2fs_get_section_mtime(struct f2fs_sb_info *sbi,
unsigned int segno);
#define DEF_FRAGMENT_SIZE 4
#define MIN_FRAGMENT_SIZE 1

View File

@ -361,20 +361,15 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
{
struct sit_info *sit_i = SIT_I(sbi);
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
unsigned int start = GET_SEG_FROM_SEC(sbi, secno);
unsigned long long mtime = 0;
unsigned int vblocks;
unsigned char age = 0;
unsigned char u;
unsigned int i;
unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi);
for (i = 0; i < usable_segs_per_sec; i++)
mtime += get_seg_entry(sbi, start + i)->mtime;
mtime = f2fs_get_section_mtime(sbi, segno);
f2fs_bug_on(sbi, mtime == INVALID_MTIME);
vblocks = get_valid_blocks(sbi, segno, true);
mtime = div_u64(mtime, usable_segs_per_sec);
vblocks = div_u64(vblocks, usable_segs_per_sec);
u = BLKS_TO_SEGS(sbi, vblocks * 100);
@ -519,10 +514,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
struct victim_sel_policy *p, unsigned int segno)
{
struct sit_info *sit_i = SIT_I(sbi);
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
unsigned int start = GET_SEG_FROM_SEC(sbi, secno);
unsigned long long mtime = 0;
unsigned int i;
if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
if (p->gc_mode == GC_AT &&
@ -530,9 +522,8 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
return;
}
for (i = 0; i < SEGS_PER_SEC(sbi); i++)
mtime += get_seg_entry(sbi, start + i)->mtime;
mtime = div_u64(mtime, SEGS_PER_SEC(sbi));
mtime = f2fs_get_section_mtime(sbi, segno);
f2fs_bug_on(sbi, mtime == INVALID_MTIME);
/* Handle if the system time has changed by the user */
if (mtime < sit_i->min_mtime)

View File

@ -5430,6 +5430,35 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi)
return SEGS_PER_SEC(sbi);
}
unsigned long long f2fs_get_section_mtime(struct f2fs_sb_info *sbi,
unsigned int segno)
{
unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi);
unsigned int secno = 0, start = 0;
unsigned int total_valid_blocks = 0;
unsigned long long mtime = 0;
unsigned int i = 0;
secno = GET_SEC_FROM_SEG(sbi, segno);
start = GET_SEG_FROM_SEC(sbi, secno);
if (!__is_large_section(sbi))
return get_seg_entry(sbi, start + i)->mtime;
for (i = 0; i < usable_segs_per_sec; i++) {
/* for large section, only check the mtime of valid segments */
struct seg_entry *se = get_seg_entry(sbi, start+i);
mtime += se->mtime * se->valid_blocks;
total_valid_blocks += se->valid_blocks;
}
if (total_valid_blocks == 0)
return INVALID_MTIME;
return div_u64(mtime, total_valid_blocks);
}
/*
* Update min, max modified time for cost-benefit GC algorithm
*/
@ -5443,13 +5472,9 @@ static void init_min_max_mtime(struct f2fs_sb_info *sbi)
sit_i->min_mtime = ULLONG_MAX;
for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
unsigned int i;
unsigned long long mtime = 0;
for (i = 0; i < SEGS_PER_SEC(sbi); i++)
mtime += get_seg_entry(sbi, segno + i)->mtime;
mtime = div_u64(mtime, SEGS_PER_SEC(sbi));
mtime = f2fs_get_section_mtime(sbi, segno);
if (sit_i->min_mtime > mtime)
sit_i->min_mtime = mtime;

View File

@ -18,6 +18,8 @@
#define F2FS_MIN_SEGMENTS 9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */
#define F2FS_MIN_META_SEGMENTS 8 /* SB + 2 (CP + SIT + NAT) + SSA */
#define INVALID_MTIME ULLONG_MAX /* no valid blocks in a segment/section */
/* L: Logical segment # in volume, R: Relative segment # in main area */
#define GET_L2R_SEGNO(free_i, segno) ((segno) - (free_i)->start_segno)
#define GET_R2L_SEGNO(free_i, segno) ((segno) + (free_i)->start_segno)