Skip to content

Commit 093749e

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: support age threshold based garbage collection
There are several issues in current background GC algorithm: - valid blocks is one of key factors during cost overhead calculation, so if segment has less valid block, however even its age is young or it locates hot segment, CB algorithm will still choose the segment as victim, it's not appropriate. - GCed data/node will go to existing logs, no matter in-there datas' update frequency is the same or not, it may mix hot and cold data again. - GC alloctor mainly use LFS type segment, it will cost free segment more quickly. This patch introduces a new algorithm named age threshold based garbage collection to solve above issues, there are three steps mainly: 1. select a source victim: - set an age threshold, and select candidates beased threshold: e.g. 0 means youngest, 100 means oldest, if we set age threshold to 80 then select dirty segments which has age in range of [80, 100] as candiddates; - set candidate_ratio threshold, and select candidates based the ratio, so that we can shrink candidates to those oldest segments; - select target segment with fewest valid blocks in order to migrate blocks with minimum cost; 2. select a target victim: - select candidates beased age threshold; - set candidate_radius threshold, search candidates whose age is around source victims, searching radius should less than the radius threshold. - select target segment with most valid blocks in order to avoid migrating current target segment. 3. merge valid blocks from source victim into target victim with SSR alloctor. Test steps: - create 160 dirty segments: * half of them have 128 valid blocks per segment * left of them have 384 valid blocks per segment - run background GC Benefit: GC count and block movement count both decrease obviously: - Before: - Valid: 86 - Dirty: 1 - Prefree: 11 - Free: 6001 (6001) GC calls: 162 (BG: 220) - data segments : 160 (160) - node segments : 2 (2) Try to move 41454 blocks (BG: 41454) - data blocks : 40960 (40960) - node blocks : 494 (494) IPU: 0 blocks SSR: 0 blocks in 0 segments LFS: 41364 blocks in 81 segments - After: - Valid: 87 - Dirty: 0 - Prefree: 4 - Free: 6008 (6008) GC calls: 75 (BG: 76) - data segments : 74 (74) - node segments : 1 (1) Try to move 12813 blocks (BG: 12813) - data blocks : 12544 (12544) - node blocks : 269 (269) IPU: 0 blocks SSR: 12032 blocks in 77 segments LFS: 855 blocks in 2 segments Signed-off-by: Chao Yu <yuchao0@huawei.com> [Jaegeuk Kim: fix a bug along with pinfile in-mem segment & clean up] Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 568d2a1 commit 093749e

File tree

13 files changed

+632
-64
lines changed

13 files changed

+632
-64
lines changed

Documentation/ABI/testing/sysfs-fs-f2fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Contact: "Namjae Jeon" <namjae.jeon@samsung.com>
2222
Description: Controls the victim selection policy for garbage collection.
2323
Setting gc_idle = 0(default) will disable this option. Setting
2424
gc_idle = 1 will select the Cost Benefit approach & setting
25-
gc_idle = 2 will select the greedy approach.
25+
gc_idle = 2 will select the greedy approach & setting
26+
gc_idle = 3 will select the age-threshold based approach.
2627

2728
What: /sys/fs/f2fs/<disk>/reclaim_segments
2829
Date: October 2013

Documentation/filesystems/f2fs.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ inlinecrypt When possible, encrypt/decrypt the contents of encrypted
266266
inline encryption hardware. The on-disk format is
267267
unaffected. For more details, see
268268
Documentation/block/inline-encryption.rst.
269+
atgc Enable age-threshold garbage collection, it provides high
270+
effectiveness and efficiency on background GC.
269271
======================== ============================================================
270272

271273
Debugfs Entries

fs/f2fs/checkpoint.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,15 +1620,15 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
16201620
f2fs_flush_sit_entries(sbi, cpc);
16211621

16221622
/* save inmem log status */
1623-
f2fs_save_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
1623+
f2fs_save_inmem_curseg(sbi);
16241624

16251625
err = do_checkpoint(sbi, cpc);
16261626
if (err)
16271627
f2fs_release_discard_addrs(sbi);
16281628
else
16291629
f2fs_clear_prefree_segments(sbi, cpc);
16301630

1631-
f2fs_restore_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
1631+
f2fs_restore_inmem_curseg(sbi);
16321632
stop:
16331633
unblock_operations(sbi);
16341634
stat_inc_cp_count(sbi->stat_info);

fs/f2fs/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
14161416
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
14171417
old_blkaddr = dn->data_blkaddr;
14181418
f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
1419-
&sum, seg_type, NULL, false);
1419+
&sum, seg_type, NULL);
14201420
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
14211421
invalidate_mapping_pages(META_MAPPING(sbi),
14221422
old_blkaddr, old_blkaddr);

fs/f2fs/debug.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,10 @@ static int stat_show(struct seq_file *s, void *v)
397397
si->curseg[CURSEG_COLD_DATA_PINNED],
398398
si->cursec[CURSEG_COLD_DATA_PINNED],
399399
si->curzone[CURSEG_COLD_DATA_PINNED]);
400+
seq_printf(s, " - ATGC data: %8d %8d %8d\n",
401+
si->curseg[CURSEG_ALL_DATA_ATGC],
402+
si->cursec[CURSEG_ALL_DATA_ATGC],
403+
si->curzone[CURSEG_ALL_DATA_ATGC]);
400404
seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
401405
si->main_area_segs - si->dirty_count -
402406
si->prefree_count - si->free_segs,

fs/f2fs/f2fs.h

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern const char *f2fs_fault_name[FAULT_MAX];
9898
#define F2FS_MOUNT_RESERVE_ROOT 0x01000000
9999
#define F2FS_MOUNT_DISABLE_CHECKPOINT 0x02000000
100100
#define F2FS_MOUNT_NORECOVERY 0x04000000
101+
#define F2FS_MOUNT_ATGC 0x08000000
101102

102103
#define F2FS_OPTION(sbi) ((sbi)->mount_opt)
103104
#define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option)
@@ -978,7 +979,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
978979
*/
979980
#define NR_CURSEG_DATA_TYPE (3)
980981
#define NR_CURSEG_NODE_TYPE (3)
981-
#define NR_CURSEG_INMEM_TYPE (1)
982+
#define NR_CURSEG_INMEM_TYPE (2)
982983
#define NR_CURSEG_PERSIST_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
983984
#define NR_CURSEG_TYPE (NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
984985

@@ -992,6 +993,7 @@ enum {
992993
NR_PERSISTENT_LOG, /* number of persistent log */
993994
CURSEG_COLD_DATA_PINNED = NR_PERSISTENT_LOG,
994995
/* pinned file that needs consecutive block address */
996+
CURSEG_ALL_DATA_ATGC, /* SSR alloctor in hot/warm/cold data area */
995997
NO_CHECK_TYPE, /* number of persistent & inmem log */
996998
};
997999

@@ -1238,6 +1240,18 @@ struct inode_management {
12381240
unsigned long ino_num; /* number of entries */
12391241
};
12401242

1243+
/* for GC_AT */
1244+
struct atgc_management {
1245+
bool atgc_enabled; /* ATGC is enabled or not */
1246+
struct rb_root_cached root; /* root of victim rb-tree */
1247+
struct list_head victim_list; /* linked with all victim entries */
1248+
unsigned int victim_count; /* victim count in rb-tree */
1249+
unsigned int candidate_ratio; /* candidate ratio */
1250+
unsigned int max_candidate_count; /* max candidate count */
1251+
unsigned int age_weight; /* age weight, vblock_weight = 100 - age_weight */
1252+
unsigned long long age_threshold; /* age threshold */
1253+
};
1254+
12411255
/* For s_flag in struct f2fs_sb_info */
12421256
enum {
12431257
SBI_IS_DIRTY, /* dirty flag for checkpoint */
@@ -1270,6 +1284,7 @@ enum {
12701284
GC_NORMAL,
12711285
GC_IDLE_CB,
12721286
GC_IDLE_GREEDY,
1287+
GC_IDLE_AT,
12731288
GC_URGENT_HIGH,
12741289
GC_URGENT_LOW,
12751290
};
@@ -1521,6 +1536,7 @@ struct f2fs_sb_info {
15211536
* race between GC and GC or CP
15221537
*/
15231538
struct f2fs_gc_kthread *gc_thread; /* GC thread */
1539+
struct atgc_management am; /* atgc management */
15241540
unsigned int cur_victim_sec; /* current victim section num */
15251541
unsigned int gc_mode; /* current GC state */
15261542
unsigned int next_victim_seg[2]; /* next segment in victim section */
@@ -3338,8 +3354,11 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
33383354
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
33393355
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
33403356
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
3341-
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type);
3342-
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type);
3357+
void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
3358+
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
3359+
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
3360+
void f2fs_get_new_segment(struct f2fs_sb_info *sbi,
3361+
unsigned int *newseg, bool new_sec, int dir);
33433362
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
33443363
unsigned int start, unsigned int end);
33453364
void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);
@@ -3367,7 +3386,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
33673386
void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
33683387
block_t old_blkaddr, block_t *new_blkaddr,
33693388
struct f2fs_summary *sum, int type,
3370-
struct f2fs_io_info *fio, bool from_gc);
3389+
struct f2fs_io_info *fio);
33713390
void f2fs_wait_on_page_writeback(struct page *page,
33723391
enum page_type type, bool ordered, bool locked);
33733392
void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr);
@@ -3506,6 +3525,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background,
35063525
unsigned int segno);
35073526
void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
35083527
int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count);
3528+
int __init f2fs_create_garbage_collection_cache(void);
3529+
void f2fs_destroy_garbage_collection_cache(void);
35093530

35103531
/*
35113532
* recovery.c

0 commit comments

Comments
 (0)