aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/segment.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/segment.c')
-rw-r--r--fs/f2fs/segment.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index fa30c117b4cc..a009f8a70c3d 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -631,7 +631,8 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
631static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi, 631static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi,
632 struct bio *bio, block_t lstart, block_t len) 632 struct bio *bio, block_t lstart, block_t len)
633{ 633{
634 struct list_head *wait_list = &(SM_I(sbi)->discard_cmd_list); 634 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
635 struct list_head *cmd_list = &(dcc->discard_cmd_list);
635 struct discard_cmd *dc; 636 struct discard_cmd *dc;
636 637
637 dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS); 638 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 dc->lstart = lstart; 641 dc->lstart = lstart;
641 dc->len = len; 642 dc->len = len;
642 init_completion(&dc->wait); 643 init_completion(&dc->wait);
643 list_add_tail(&dc->list, wait_list); 644 list_add_tail(&dc->list, cmd_list);
644 645
645 return dc; 646 return dc;
646} 647}
@@ -648,7 +649,8 @@ static struct discard_cmd *__add_discard_cmd(struct f2fs_sb_info *sbi,
648/* This should be covered by global mutex, &sit_i->sentry_lock */ 649/* This should be covered by global mutex, &sit_i->sentry_lock */
649void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) 650void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
650{ 651{
651 struct list_head *wait_list = &(SM_I(sbi)->discard_cmd_list); 652 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
653 struct list_head *wait_list = &(dcc->discard_cmd_list);
652 struct discard_cmd *dc, *tmp; 654 struct discard_cmd *dc, *tmp;
653 655
654 list_for_each_entry_safe(dc, tmp, wait_list, list) { 656 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 struct cp_control *cpc, struct seg_entry *se, 819 struct cp_control *cpc, struct seg_entry *se,
818 unsigned int start, unsigned int end) 820 unsigned int start, unsigned int end)
819{ 821{
820 struct list_head *head = &SM_I(sbi)->discard_entry_list; 822 struct list_head *head = &SM_I(sbi)->dcc_info->discard_entry_list;
821 struct discard_entry *new, *last; 823 struct discard_entry *new, *last;
822 824
823 if (!list_empty(head)) { 825 if (!list_empty(head)) {
@@ -835,7 +837,7 @@ static void __add_discard_entry(struct f2fs_sb_info *sbi,
835 new->len = end - start; 837 new->len = end - start;
836 list_add_tail(&new->list, head); 838 list_add_tail(&new->list, head);
837done: 839done:
838 SM_I(sbi)->nr_discards += end - start; 840 SM_I(sbi)->dcc_info->nr_discards += end - start;
839} 841}
840 842
841static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc, 843static 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 859
858 if (!force) { 860 if (!force) {
859 if (!test_opt(sbi, DISCARD) || !se->valid_blocks || 861 if (!test_opt(sbi, DISCARD) || !se->valid_blocks ||
860 SM_I(sbi)->nr_discards >= SM_I(sbi)->max_discards) 862 SM_I(sbi)->dcc_info->nr_discards >=
863 SM_I(sbi)->dcc_info->max_discards)
861 return false; 864 return false;
862 } 865 }
863 866
@@ -866,7 +869,8 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
866 dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] : 869 dmap[i] = force ? ~ckpt_map[i] & ~discard_map[i] :
867 (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; 870 (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i];
868 871
869 while (force || SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { 872 while (force || SM_I(sbi)->dcc_info->nr_discards <=
873 SM_I(sbi)->dcc_info->max_discards) {
870 start = __find_rev_next_bit(dmap, max_blocks, end + 1); 874 start = __find_rev_next_bit(dmap, max_blocks, end + 1);
871 if (start >= max_blocks) 875 if (start >= max_blocks)
872 break; 876 break;
@@ -886,7 +890,7 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
886 890
887void release_discard_addrs(struct f2fs_sb_info *sbi) 891void release_discard_addrs(struct f2fs_sb_info *sbi)
888{ 892{
889 struct list_head *head = &(SM_I(sbi)->discard_entry_list); 893 struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list);
890 struct discard_entry *entry, *this; 894 struct discard_entry *entry, *this;
891 895
892 /* drop caches */ 896 /* drop caches */
@@ -912,7 +916,7 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
912 916
913void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc) 917void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
914{ 918{
915 struct list_head *head = &(SM_I(sbi)->discard_entry_list); 919 struct list_head *head = &(SM_I(sbi)->dcc_info->discard_entry_list);
916 struct discard_entry *entry, *this; 920 struct discard_entry *entry, *this;
917 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 921 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
918 struct blk_plug plug; 922 struct blk_plug plug;
@@ -972,13 +976,47 @@ next:
972 cpc->trimmed += entry->len; 976 cpc->trimmed += entry->len;
973skip: 977skip:
974 list_del(&entry->list); 978 list_del(&entry->list);
975 SM_I(sbi)->nr_discards -= entry->len; 979 SM_I(sbi)->dcc_info->nr_discards -= entry->len;
976 kmem_cache_free(discard_entry_slab, entry); 980 kmem_cache_free(discard_entry_slab, entry);
977 } 981 }
978 982
979 blk_finish_plug(&plug); 983 blk_finish_plug(&plug);
980} 984}
981 985
986int create_discard_cmd_control(struct f2fs_sb_info *sbi)
987{
988 struct discard_cmd_control *dcc;
989 int err = 0;
990
991 if (SM_I(sbi)->dcc_info) {
992 dcc = SM_I(sbi)->dcc_info;
993 goto init_thread;
994 }
995
996 dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL);
997 if (!dcc)
998 return -ENOMEM;
999
1000 INIT_LIST_HEAD(&dcc->discard_entry_list);
1001 INIT_LIST_HEAD(&dcc->discard_cmd_list);
1002 dcc->nr_discards = 0;
1003 dcc->max_discards = 0;
1004
1005 SM_I(sbi)->dcc_info = dcc;
1006init_thread:
1007 return err;
1008}
1009
1010void destroy_discard_cmd_control(struct f2fs_sb_info *sbi, bool free)
1011{
1012 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
1013
1014 if (free) {
1015 kfree(dcc);
1016 SM_I(sbi)->dcc_info = NULL;
1017 }
1018}
1019
982static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) 1020static bool __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
983{ 1021{
984 struct sit_info *sit_i = SIT_I(sbi); 1022 struct sit_info *sit_i = SIT_I(sbi);
@@ -2708,11 +2746,6 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
2708 sm_info->min_ipu_util = DEF_MIN_IPU_UTIL; 2746 sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
2709 sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS; 2747 sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;
2710 2748
2711 INIT_LIST_HEAD(&sm_info->discard_entry_list);
2712 INIT_LIST_HEAD(&sm_info->discard_cmd_list);
2713 sm_info->nr_discards = 0;
2714 sm_info->max_discards = 0;
2715
2716 sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS; 2749 sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS;
2717 2750
2718 INIT_LIST_HEAD(&sm_info->sit_entry_set); 2751 INIT_LIST_HEAD(&sm_info->sit_entry_set);
@@ -2723,6 +2756,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
2723 return err; 2756 return err;
2724 } 2757 }
2725 2758
2759 err = create_discard_cmd_control(sbi);
2760 if (err)
2761 return err;
2762
2726 err = build_sit_info(sbi); 2763 err = build_sit_info(sbi);
2727 if (err) 2764 if (err)
2728 return err; 2765 return err;
@@ -2844,6 +2881,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
2844 if (!sm_info) 2881 if (!sm_info)
2845 return; 2882 return;
2846 destroy_flush_cmd_control(sbi, true); 2883 destroy_flush_cmd_control(sbi, true);
2884 destroy_discard_cmd_control(sbi, true);
2847 destroy_dirty_segmap(sbi); 2885 destroy_dirty_segmap(sbi);
2848 destroy_curseg(sbi); 2886 destroy_curseg(sbi);
2849 destroy_free_segmap(sbi); 2887 destroy_free_segmap(sbi);