Commit bba681cb authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: introduce a batched trim

This patch introduces a batched trimming feature, which submits split discard
commands.

This is to avoid long latency due to huge trim commands.
If fstrim was triggered ranging from 0 to the end of device, we should lock
all the checkpoint-related mutexes, resulting in very long latency.
Reviewed-by: default avatarChao Yu <chao2.yu@samsung.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 487261f3
...@@ -74,3 +74,9 @@ Date: March 2014 ...@@ -74,3 +74,9 @@ Date: March 2014
Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description: Description:
Controls the memory footprint used by f2fs. Controls the memory footprint used by f2fs.
What: /sys/fs/f2fs/<disk>/trim_sections
Date: February 2015
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description:
Controls the trimming rate in batch mode.
...@@ -199,6 +199,10 @@ Files in /sys/fs/f2fs/<devname> ...@@ -199,6 +199,10 @@ Files in /sys/fs/f2fs/<devname>
checkpoint is triggered, and issued during the checkpoint is triggered, and issued during the
checkpoint. By default, it is disabled with 0. checkpoint. By default, it is disabled with 0.
trim_sections This parameter controls the number of sections
to be trimmed out in batch mode when FITRIM
conducts. 32 sections is set by default.
ipu_policy This parameter controls the policy of in-place ipu_policy This parameter controls the policy of in-place
updates in f2fs. There are five policies: updates in f2fs. There are five policies:
0x01: F2FS_IPU_FORCE, 0x02: F2FS_IPU_SSR, 0x01: F2FS_IPU_FORCE, 0x02: F2FS_IPU_SSR,
......
...@@ -105,6 +105,10 @@ enum { ...@@ -105,6 +105,10 @@ enum {
CP_DISCARD, CP_DISCARD,
}; };
#define DEF_BATCHED_TRIM_SECTIONS 32
#define BATCHED_TRIM_SEGMENTS(sbi) \
(SM_I(sbi)->trim_sections * (sbi)->segs_per_sec)
struct cp_control { struct cp_control {
int reason; int reason;
__u64 trim_start; __u64 trim_start;
...@@ -448,6 +452,9 @@ struct f2fs_sm_info { ...@@ -448,6 +452,9 @@ struct f2fs_sm_info {
int nr_discards; /* # of discards in the list */ int nr_discards; /* # of discards in the list */
int max_discards; /* max. discards to be issued */ int max_discards; /* max. discards to be issued */
/* for batched trimming */
unsigned int trim_sections; /* # of sections to trim */
struct list_head sit_entry_set; /* sit entry set list */ struct list_head sit_entry_set; /* sit entry set list */
unsigned int ipu_policy; /* in-place-update policy */ unsigned int ipu_policy; /* in-place-update policy */
......
...@@ -1066,14 +1066,19 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) ...@@ -1066,14 +1066,19 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
end_segno = (end >= MAX_BLKADDR(sbi)) ? MAIN_SEGS(sbi) - 1 : end_segno = (end >= MAX_BLKADDR(sbi)) ? MAIN_SEGS(sbi) - 1 :
GET_SEGNO(sbi, end); GET_SEGNO(sbi, end);
cpc.reason = CP_DISCARD; cpc.reason = CP_DISCARD;
cpc.trim_start = start_segno;
cpc.trim_end = end_segno;
cpc.trim_minlen = range->minlen >> sbi->log_blocksize; cpc.trim_minlen = range->minlen >> sbi->log_blocksize;
/* do checkpoint to issue discard commands safely */ /* do checkpoint to issue discard commands safely */
mutex_lock(&sbi->gc_mutex); for (; start_segno <= end_segno; start_segno = cpc.trim_end + 1) {
write_checkpoint(sbi, &cpc); cpc.trim_start = start_segno;
mutex_unlock(&sbi->gc_mutex); cpc.trim_end = min_t(unsigned int, rounddown(start_segno +
BATCHED_TRIM_SEGMENTS(sbi),
sbi->segs_per_sec) - 1, end_segno);
mutex_lock(&sbi->gc_mutex);
write_checkpoint(sbi, &cpc);
mutex_unlock(&sbi->gc_mutex);
}
out: out:
range->len = cpc.trimmed << sbi->log_blocksize; range->len = cpc.trimmed << sbi->log_blocksize;
return 0; return 0;
...@@ -2127,6 +2132,8 @@ int build_segment_manager(struct f2fs_sb_info *sbi) ...@@ -2127,6 +2132,8 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
sm_info->nr_discards = 0; sm_info->nr_discards = 0;
sm_info->max_discards = 0; sm_info->max_discards = 0;
sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS;
INIT_LIST_HEAD(&sm_info->sit_entry_set); INIT_LIST_HEAD(&sm_info->sit_entry_set);
if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) { if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) {
......
...@@ -195,6 +195,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); ...@@ -195,6 +195,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks);
...@@ -210,6 +211,7 @@ static struct attribute *f2fs_attrs[] = { ...@@ -210,6 +211,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(gc_idle), ATTR_LIST(gc_idle),
ATTR_LIST(reclaim_segments), ATTR_LIST(reclaim_segments),
ATTR_LIST(max_small_discards), ATTR_LIST(max_small_discards),
ATTR_LIST(batched_trim_sections),
ATTR_LIST(ipu_policy), ATTR_LIST(ipu_policy),
ATTR_LIST(min_ipu_util), ATTR_LIST(min_ipu_util),
ATTR_LIST(min_fsync_blocks), ATTR_LIST(min_fsync_blocks),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment