Commit 0b54fb84 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: factor out discard command info into discard_cmd_control

This patch adds discard_cmd_control with the existing discarding controls.
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent d4adb30f
...@@ -196,6 +196,8 @@ static void update_mem_info(struct f2fs_sb_info *sbi) ...@@ -196,6 +196,8 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
/* build merge flush thread */ /* build merge flush thread */
if (SM_I(sbi)->fcc_info) if (SM_I(sbi)->fcc_info)
si->cache_mem += sizeof(struct flush_cmd_control); si->cache_mem += sizeof(struct flush_cmd_control);
if (SM_I(sbi)->dcc_info)
si->cache_mem += sizeof(struct discard_cmd_control);
/* free nids */ /* free nids */
si->cache_mem += (NM_I(sbi)->nid_cnt[FREE_NID_LIST] + si->cache_mem += (NM_I(sbi)->nid_cnt[FREE_NID_LIST] +
......
...@@ -189,6 +189,13 @@ struct discard_cmd { ...@@ -189,6 +189,13 @@ struct discard_cmd {
struct bio *bio; /* bio */ struct bio *bio; /* bio */
}; };
struct discard_cmd_control {
struct list_head discard_entry_list; /* 4KB discard entry list */
int nr_discards; /* # of discards in the list */
struct list_head discard_cmd_list; /* discard cmd list */
int max_discards; /* max. discards to be issued */
};
/* for the list of fsync inodes, used only during recovery */ /* for the list of fsync inodes, used only during recovery */
struct fsync_inode_entry { struct fsync_inode_entry {
struct list_head list; /* list head */ struct list_head list; /* list head */
...@@ -632,12 +639,6 @@ struct f2fs_sm_info { ...@@ -632,12 +639,6 @@ struct f2fs_sm_info {
/* a threshold to reclaim prefree segments */ /* a threshold to reclaim prefree segments */
unsigned int rec_prefree_segments; unsigned int rec_prefree_segments;
/* for small discard management */
struct list_head discard_entry_list; /* 4KB discard entry list */
struct list_head discard_cmd_list; /* discard cmd list */
int nr_discards; /* # of discards in the list */
int max_discards; /* max. discards to be issued */
/* for batched trimming */ /* for batched trimming */
unsigned int trim_sections; /* # of sections to trim */ unsigned int trim_sections; /* # of sections to trim */
...@@ -649,6 +650,9 @@ struct f2fs_sm_info { ...@@ -649,6 +650,9 @@ struct f2fs_sm_info {
/* for flush command control */ /* for flush command control */
struct flush_cmd_control *fcc_info; struct flush_cmd_control *fcc_info;
/* for discard command control */
struct discard_cmd_control *dcc_info;
}; };
/* /*
......
...@@ -631,7 +631,8 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) ...@@ -631,7 +631,8 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi, static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi,
struct bio *bio, block_t lstart, block_t len) struct bio *bio, block_t lstart, block_t len)
{ {
struct list_head *wait_list = &(SM_I(sbi)->discard_cmd_list); struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct list_head *cmd_list = &(dcc->discard_cmd_list);
struct discard_cmd *dc; struct discard_cmd *dc;
dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS); dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS);
...@@ -640,7 +641,7 @@ static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -640,7 +641,7 @@ static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi,
dc->lstart = lstart; dc->lstart = lstart;
dc->len = len; dc->len = len;
init_completion(&dc->wait); init_completion(&dc->wait);
list_add_tail(&dc->list, wait_list); list_add_tail(&dc->list, cmd_list);
return dc; return dc;
} }
...@@ -648,7 +649,8 @@ static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi, ...@@ -648,7 +649,8 @@ static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi,
/* This should be covered by global mutex, &sit_i->sentry_lock */ /* This should be covered by global mutex, &sit_i->sentry_lock */
void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
{ {
struct list_head *wait_list = &(SM_I(sbi)->discard_cmd_list); struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct list_head *wait_list = &(dcc->discard_cmd_list);
struct discard_cmd *dc, *tmp; struct discard_cmd *dc, *tmp;
list_for_each_entry_safe(dc, tmp, wait_list, list) { list_for_each_entry_safe(dc, tmp, wait_list, list) {
...@@ -817,7 +819,7 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi, ...@@ -817,7 +819,7 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi,
struct cp_control *cpc, struct seg_entry *se, struct cp_control *cpc, struct seg_entry *se,
unsigned int start, unsigned int end) unsigned int start, unsigned int end)
{ {
struct list_head *head = &SM_I(sbi)->discard_entry_list; struct list_head *head = &SM_I(sbi)->dcc_info->discard_entry_list;
struct discard_entry *new, *last; struct discard_entry *new, *last;
if (!list_empty(head)) { if (!list_empty(head)) {
...@@ -835,7 +837,7 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi, ...@@ -835,7 +837,7 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi,
new->len = end - start; new->len = end - start;
list_add_tail(&new->list, head); list_add_tail(&new->list, head);
done: done:
SM_I(sbi)->nr_discards += end - start; SM_I(sbi)->dcc_info->nr_discards += end - start;
} }
static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
...@@ -857,7 +859,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, ...@@ -857,7 +859,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
if (!force) { if (!force) {
if (!test_opt(sbi, DISCARD) || !se->valid_blocks || if (!test_opt(sbi, DISCARD) || !se->valid_blocks ||
SM_I(sbi)->nr_discards >= SM_I(sbi)->max_discards) SM_I(sbi)->dcc_info->nr_discards >=
SM_I(sbi)->dcc_info->max_discards)
return false; return false;
} }
...@@ -866,7 +869,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, ...@@ -866,7 +869,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] : dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] :
(cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i];
while (force || SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { while (force || SM_I(sbi)->dcc_info->nr_discards <=
SM_I(sbi)->dcc_info->max_discards) {
start = __find_rev_next_bit(dmap, max_blocks, end + 1); start = __find_rev_next_bit(dmap, max_blocks, end + 1);
if (start >= max_blocks) if (start >= max_blocks)
break; break;
...@@ -886,7 +890,7 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, ...@@ -886,7 +890,7 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
void release_discard_addrs(struct f2fs_sb_info *sbi) void release_discard_addrs(struct f2fs_sb_info *sbi)
{ {
struct list_head *head = &(SM_I(sbi)->discard_entry_list); struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list);
struct discard_entry *entry, *this; struct discard_entry *entry, *this;
/* drop caches */ /* drop caches */
...@@ -912,7 +916,7 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) ...@@ -912,7 +916,7 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{ {
struct list_head *head = &(SM_I(sbi)->discard_entry_list); struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list);
struct discard_entry *entry, *this; struct discard_entry *entry, *this;
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
struct blk_plug plug; struct blk_plug plug;
...@@ -972,13 +976,47 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -972,13 +976,47 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
cpc->trimmed += entry->len; cpc->trimmed += entry->len;
skip: skip:
list_del(&entry->list); list_del(&entry->list);
SM_I(sbi)->nr_discards -= entry->len; SM_I(sbi)->dcc_info->nr_discards -= entry->len;
kmem_cache_free(discard_entry_slab, entry); kmem_cache_free(discard_entry_slab, entry);
} }
blk_finish_plug(&plug); blk_finish_plug(&plug);
} }
int create_discard_cmd_control(struct f2fs_sb_info *sbi)
{
struct discard_cmd_control *dcc;
int err = 0;
if (SM_I(sbi)->dcc_info) {
dcc = SM_I(sbi)->dcc_info;
goto init_thread;
}
dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL);
if (!dcc)
return -ENOMEM;
INIT_LIST_HEAD(&dcc->discard_entry_list);
INIT_LIST_HEAD(&dcc->discard_cmd_list);
dcc->nr_discards = 0;
dcc->max_discards = 0;
SM_I(sbi)->dcc_info = dcc;
init_thread:
return err;
}
void destroy_discard_cmd_control(struct f2fs_sb_info *sbi, bool free)
{
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
if (free) {
kfree(dcc);
SM_I(sbi)->dcc_info = NULL;
}
}
static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
{ {
struct sit_info *sit_i = SIT_I(sbi); struct sit_info *sit_i = SIT_I(sbi);
...@@ -2708,11 +2746,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi) ...@@ -2708,11 +2746,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
sm_info->min_ipu_util = DEF_MIN_IPU_UTIL; sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS; sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;
INIT_LIST_HEAD(&sm_info->discard_entry_list);
INIT_LIST_HEAD(&sm_info->discard_cmd_list);
sm_info->nr_discards = 0;
sm_info->max_discards = 0;
sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS;
INIT_LIST_HEAD(&sm_info->sit_entry_set); INIT_LIST_HEAD(&sm_info->sit_entry_set);
...@@ -2723,6 +2756,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi) ...@@ -2723,6 +2756,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
return err; return err;
} }
err = create_discard_cmd_control(sbi);
if (err)
return err;
err = build_sit_info(sbi); err = build_sit_info(sbi);
if (err) if (err)
return err; return err;
...@@ -2844,6 +2881,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi) ...@@ -2844,6 +2881,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
if (!sm_info) if (!sm_info)
return; return;
destroy_flush_cmd_control(sbi, true); destroy_flush_cmd_control(sbi, true);
destroy_discard_cmd_control(sbi, true);
destroy_dirty_segmap(sbi); destroy_dirty_segmap(sbi);
destroy_curseg(sbi); destroy_curseg(sbi);
destroy_free_segmap(sbi); destroy_free_segmap(sbi);
......
...@@ -145,6 +145,7 @@ static match_table_t f2fs_tokens = { ...@@ -145,6 +145,7 @@ static match_table_t f2fs_tokens = {
enum { enum {
GC_THREAD, /* struct f2fs_gc_thread */ GC_THREAD, /* struct f2fs_gc_thread */
SM_INFO, /* struct f2fs_sm_info */ SM_INFO, /* struct f2fs_sm_info */
DCC_INFO, /* struct discard_cmd_control */
NM_INFO, /* struct f2fs_nm_info */ NM_INFO, /* struct f2fs_nm_info */
F2FS_SBI, /* struct f2fs_sb_info */ F2FS_SBI, /* struct f2fs_sb_info */
#ifdef CONFIG_F2FS_FAULT_INJECTION #ifdef CONFIG_F2FS_FAULT_INJECTION
...@@ -168,6 +169,8 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) ...@@ -168,6 +169,8 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
return (unsigned char *)sbi->gc_thread; return (unsigned char *)sbi->gc_thread;
else if (struct_type == SM_INFO) else if (struct_type == SM_INFO)
return (unsigned char *)SM_I(sbi); return (unsigned char *)SM_I(sbi);
else if (struct_type == DCC_INFO)
return (unsigned char *)SM_I(sbi)->dcc_info;
else if (struct_type == NM_INFO) else if (struct_type == NM_INFO)
return (unsigned char *)NM_I(sbi); return (unsigned char *)NM_I(sbi);
else if (struct_type == F2FS_SBI) else if (struct_type == F2FS_SBI)
...@@ -283,7 +286,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); ...@@ -283,7 +286,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
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_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(DCC_INFO, discard_cmd_control, 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, 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);
......
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