segment.c (46f84c2c058784f42f2d021df79384ec66cdb256) | segment.c (ba48a33ef6faa573257b2a4181329f2d1eaafed9) |
---|---|
1/* 2 * fs/f2fs/segment.c 3 * 4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com/ 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as --- 663 unchanged lines hidden (view full) --- 672 mutex_unlock(&dirty_i->seglist_lock); 673} 674 675static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, 676 struct block_device *bdev, block_t lstart, 677 block_t start, block_t len) 678{ 679 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 1/* 2 * fs/f2fs/segment.c 3 * 4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. 5 * http://www.samsung.com/ 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as --- 663 unchanged lines hidden (view full) --- 672 mutex_unlock(&dirty_i->seglist_lock); 673} 674 675static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi, 676 struct block_device *bdev, block_t lstart, 677 block_t start, block_t len) 678{ 679 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
680 struct list_head *pend_list = &(dcc->pend_list); | 680 struct list_head *pend_list; |
681 struct discard_cmd *dc; 682 | 681 struct discard_cmd *dc; 682 |
683 f2fs_bug_on(sbi, !len); 684 685 pend_list = &dcc->pend_list[plist_idx(len)]; 686 |
|
683 dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS); 684 INIT_LIST_HEAD(&dc->list); 685 dc->bdev = bdev; 686 dc->lstart = lstart; 687 dc->start = start; 688 dc->len = len; 689 dc->state = D_PREP; 690 dc->error = 0; --- 110 unchanged lines hidden (view full) --- 801do_insert: 802 dc = __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, p); 803 if (!dc) 804 return NULL; 805 806 return dc; 807} 808 | 687 dc = f2fs_kmem_cache_alloc(discard_cmd_slab, GFP_NOFS); 688 INIT_LIST_HEAD(&dc->list); 689 dc->bdev = bdev; 690 dc->lstart = lstart; 691 dc->start = start; 692 dc->len = len; 693 dc->state = D_PREP; 694 dc->error = 0; --- 110 unchanged lines hidden (view full) --- 805do_insert: 806 dc = __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, p); 807 if (!dc) 808 return NULL; 809 810 return dc; 811} 812 |
813static void __relocate_discard_cmd(struct discard_cmd_control *dcc, 814 struct discard_cmd *dc) 815{ 816 list_move_tail(&dc->list, &dcc->pend_list[plist_idx(dc->len)]); 817} 818 |
|
809static void __punch_discard_cmd(struct f2fs_sb_info *sbi, 810 struct discard_cmd *dc, block_t blkaddr) 811{ | 819static void __punch_discard_cmd(struct f2fs_sb_info *sbi, 820 struct discard_cmd *dc, block_t blkaddr) 821{ |
822 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
|
812 struct discard_info di = dc->di; 813 bool modified = false; 814 815 if (dc->state == D_DONE || dc->len == 1) { 816 __remove_discard_cmd(sbi, dc); 817 return; 818 } 819 820 if (blkaddr > di.lstart) { 821 dc->len = blkaddr - dc->lstart; | 823 struct discard_info di = dc->di; 824 bool modified = false; 825 826 if (dc->state == D_DONE || dc->len == 1) { 827 __remove_discard_cmd(sbi, dc); 828 return; 829 } 830 831 if (blkaddr > di.lstart) { 832 dc->len = blkaddr - dc->lstart; |
833 __relocate_discard_cmd(dcc, dc); |
|
822 modified = true; 823 } 824 825 if (blkaddr < di.lstart + di.len - 1) { 826 if (modified) { 827 __insert_discard_tree(sbi, dc->bdev, blkaddr + 1, 828 di.start + blkaddr + 1 - di.lstart, 829 di.lstart + di.len - 1 - blkaddr, 830 NULL, NULL); 831 } else { 832 dc->lstart++; 833 dc->len--; 834 dc->start++; | 834 modified = true; 835 } 836 837 if (blkaddr < di.lstart + di.len - 1) { 838 if (modified) { 839 __insert_discard_tree(sbi, dc->bdev, blkaddr + 1, 840 di.start + blkaddr + 1 - di.lstart, 841 di.lstart + di.len - 1 - blkaddr, 842 NULL, NULL); 843 } else { 844 dc->lstart++; 845 dc->len--; 846 dc->start++; |
847 __relocate_discard_cmd(dcc, dc); |
|
835 } 836 } 837} 838 839static void __update_discard_tree_range(struct f2fs_sb_info *sbi, 840 struct block_device *bdev, block_t lstart, 841 block_t start, block_t len) 842{ --- 42 unchanged lines hidden (view full) --- 885 886 if (!di.len) 887 goto next; 888 889 if (prev_dc && prev_dc->state == D_PREP && 890 prev_dc->bdev == bdev && 891 __is_discard_back_mergeable(&di, &prev_dc->di)) { 892 prev_dc->di.len += di.len; | 848 } 849 } 850} 851 852static void __update_discard_tree_range(struct f2fs_sb_info *sbi, 853 struct block_device *bdev, block_t lstart, 854 block_t start, block_t len) 855{ --- 42 unchanged lines hidden (view full) --- 898 899 if (!di.len) 900 goto next; 901 902 if (prev_dc && prev_dc->state == D_PREP && 903 prev_dc->bdev == bdev && 904 __is_discard_back_mergeable(&di, &prev_dc->di)) { 905 prev_dc->di.len += di.len; |
906 __relocate_discard_cmd(dcc, prev_dc); |
|
893 di = prev_dc->di; 894 tdc = prev_dc; 895 merged = true; 896 } 897 898 if (next_dc && next_dc->state == D_PREP && 899 next_dc->bdev == bdev && 900 __is_discard_front_mergeable(&di, &next_dc->di)) { 901 next_dc->di.lstart = di.lstart; 902 next_dc->di.len += di.len; 903 next_dc->di.start = di.start; | 907 di = prev_dc->di; 908 tdc = prev_dc; 909 merged = true; 910 } 911 912 if (next_dc && next_dc->state == D_PREP && 913 next_dc->bdev == bdev && 914 __is_discard_front_mergeable(&di, &next_dc->di)) { 915 next_dc->di.lstart = di.lstart; 916 next_dc->di.len += di.len; 917 next_dc->di.start = di.start; |
918 __relocate_discard_cmd(dcc, next_dc); |
|
904 if (tdc) 905 __remove_discard_cmd(sbi, tdc); 906 907 merged = true; 908 } 909 910 if (!merged) 911 __insert_discard_tree(sbi, bdev, di.lstart, di.start, --- 44 unchanged lines hidden (view full) --- 956 957 mutex_unlock(&dcc->cmd_lock); 958} 959 960/* This comes from f2fs_put_super */ 961void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi) 962{ 963 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; | 919 if (tdc) 920 __remove_discard_cmd(sbi, tdc); 921 922 merged = true; 923 } 924 925 if (!merged) 926 __insert_discard_tree(sbi, bdev, di.lstart, di.start, --- 44 unchanged lines hidden (view full) --- 971 972 mutex_unlock(&dcc->cmd_lock); 973} 974 975/* This comes from f2fs_put_super */ 976void f2fs_wait_discard_bios(struct f2fs_sb_info *sbi) 977{ 978 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; |
964 struct list_head *pend_list = &(dcc->pend_list); | 979 struct list_head *pend_list; |
965 struct list_head *wait_list = &(dcc->wait_list); 966 struct discard_cmd *dc, *tmp; 967 struct blk_plug plug; | 980 struct list_head *wait_list = &(dcc->wait_list); 981 struct discard_cmd *dc, *tmp; 982 struct blk_plug plug; |
983 int i; |
|
968 969 mutex_lock(&dcc->cmd_lock); 970 971 blk_start_plug(&plug); | 984 985 mutex_lock(&dcc->cmd_lock); 986 987 blk_start_plug(&plug); |
972 list_for_each_entry_safe(dc, tmp, pend_list, list) 973 __submit_discard_cmd(sbi, dc); | 988 for (i = 0; i < MAX_PLIST_NUM; i++) { 989 pend_list = &dcc->pend_list[i]; 990 list_for_each_entry_safe(dc, tmp, pend_list, list) 991 __submit_discard_cmd(sbi, dc); 992 } |
974 blk_finish_plug(&plug); 975 976 list_for_each_entry_safe(dc, tmp, wait_list, list) { 977 wait_for_completion_io(&dc->wait); 978 __remove_discard_cmd(sbi, dc); 979 } 980 981 mutex_unlock(&dcc->cmd_lock); 982} 983 984static int issue_discard_thread(void *data) 985{ 986 struct f2fs_sb_info *sbi = data; 987 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; 988 wait_queue_head_t *q = &dcc->discard_wait_queue; | 993 blk_finish_plug(&plug); 994 995 list_for_each_entry_safe(dc, tmp, wait_list, list) { 996 wait_for_completion_io(&dc->wait); 997 __remove_discard_cmd(sbi, dc); 998 } 999 1000 mutex_unlock(&dcc->cmd_lock); 1001} 1002 1003static int issue_discard_thread(void *data) 1004{ 1005 struct f2fs_sb_info *sbi = data; 1006 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; 1007 wait_queue_head_t *q = &dcc->discard_wait_queue; |
989 struct list_head *pend_list = &dcc->pend_list; | 1008 struct list_head *pend_list; |
990 struct list_head *wait_list = &dcc->wait_list; 991 struct discard_cmd *dc, *tmp; 992 struct blk_plug plug; | 1009 struct list_head *wait_list = &dcc->wait_list; 1010 struct discard_cmd *dc, *tmp; 1011 struct blk_plug plug; |
993 int iter = 0; | 1012 int iter = 0, i; |
994repeat: 995 if (kthread_should_stop()) 996 return 0; 997 998 mutex_lock(&dcc->cmd_lock); 999 blk_start_plug(&plug); | 1013repeat: 1014 if (kthread_should_stop()) 1015 return 0; 1016 1017 mutex_lock(&dcc->cmd_lock); 1018 blk_start_plug(&plug); |
1000 list_for_each_entry_safe(dc, tmp, pend_list, list) { 1001 f2fs_bug_on(sbi, dc->state != D_PREP); | 1019 for (i = MAX_PLIST_NUM - 1; i >= 0; i--) { 1020 pend_list = &dcc->pend_list[i]; 1021 list_for_each_entry_safe(dc, tmp, pend_list, list) { 1022 f2fs_bug_on(sbi, dc->state != D_PREP); |
1002 | 1023 |
1003 if (is_idle(sbi)) 1004 __submit_discard_cmd(sbi, dc); | 1024 if (is_idle(sbi)) 1025 __submit_discard_cmd(sbi, dc); |
1005 | 1026 |
1006 if (iter++ > DISCARD_ISSUE_RATE) 1007 break; | 1027 if (iter++ > DISCARD_ISSUE_RATE) 1028 goto next_step; 1029 } |
1008 } | 1030 } |
1031next_step: |
|
1009 blk_finish_plug(&plug); 1010 1011 list_for_each_entry_safe(dc, tmp, wait_list, list) { 1012 if (dc->state == D_DONE) { 1013 wait_for_completion_io(&dc->wait); 1014 __remove_discard_cmd(sbi, dc); 1015 } 1016 } 1017 mutex_unlock(&dcc->cmd_lock); 1018 1019 iter = 0; 1020 congestion_wait(BLK_RW_SYNC, HZ/50); 1021 1022 wait_event_interruptible(*q, kthread_should_stop() || | 1032 blk_finish_plug(&plug); 1033 1034 list_for_each_entry_safe(dc, tmp, wait_list, list) { 1035 if (dc->state == D_DONE) { 1036 wait_for_completion_io(&dc->wait); 1037 __remove_discard_cmd(sbi, dc); 1038 } 1039 } 1040 mutex_unlock(&dcc->cmd_lock); 1041 1042 iter = 0; 1043 congestion_wait(BLK_RW_SYNC, HZ/50); 1044 1045 wait_event_interruptible(*q, kthread_should_stop() || |
1023 !list_empty(pend_list) || !list_empty(wait_list)); | 1046 atomic_read(&dcc->discard_cmd_cnt)); |
1024 goto repeat; 1025} 1026 1027#ifdef CONFIG_BLK_DEV_ZONED 1028static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, 1029 struct block_device *bdev, block_t blkstart, block_t blklen) 1030{ 1031 sector_t sector, nr_sects; --- 263 unchanged lines hidden (view full) --- 1295 kmem_cache_free(discard_entry_slab, entry); 1296 } 1297} 1298 1299static int create_discard_cmd_control(struct f2fs_sb_info *sbi) 1300{ 1301 dev_t dev = sbi->sb->s_bdev->bd_dev; 1302 struct discard_cmd_control *dcc; | 1047 goto repeat; 1048} 1049 1050#ifdef CONFIG_BLK_DEV_ZONED 1051static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, 1052 struct block_device *bdev, block_t blkstart, block_t blklen) 1053{ 1054 sector_t sector, nr_sects; --- 263 unchanged lines hidden (view full) --- 1318 kmem_cache_free(discard_entry_slab, entry); 1319 } 1320} 1321 1322static int create_discard_cmd_control(struct f2fs_sb_info *sbi) 1323{ 1324 dev_t dev = sbi->sb->s_bdev->bd_dev; 1325 struct discard_cmd_control *dcc; |
1303 int err = 0; | 1326 int err = 0, i; |
1304 1305 if (SM_I(sbi)->dcc_info) { 1306 dcc = SM_I(sbi)->dcc_info; 1307 goto init_thread; 1308 } 1309 1310 dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL); 1311 if (!dcc) 1312 return -ENOMEM; 1313 1314 INIT_LIST_HEAD(&dcc->entry_list); | 1327 1328 if (SM_I(sbi)->dcc_info) { 1329 dcc = SM_I(sbi)->dcc_info; 1330 goto init_thread; 1331 } 1332 1333 dcc = kzalloc(sizeof(struct discard_cmd_control), GFP_KERNEL); 1334 if (!dcc) 1335 return -ENOMEM; 1336 1337 INIT_LIST_HEAD(&dcc->entry_list); |
1315 INIT_LIST_HEAD(&dcc->pend_list); | 1338 for (i = 0; i < MAX_PLIST_NUM; i++) 1339 INIT_LIST_HEAD(&dcc->pend_list[i]); |
1316 INIT_LIST_HEAD(&dcc->wait_list); 1317 mutex_init(&dcc->cmd_lock); 1318 atomic_set(&dcc->issued_discard, 0); 1319 atomic_set(&dcc->issing_discard, 0); 1320 atomic_set(&dcc->discard_cmd_cnt, 0); 1321 dcc->nr_discards = 0; 1322 dcc->max_discards = 0; 1323 dcc->root = RB_ROOT; --- 1971 unchanged lines hidden --- | 1340 INIT_LIST_HEAD(&dcc->wait_list); 1341 mutex_init(&dcc->cmd_lock); 1342 atomic_set(&dcc->issued_discard, 0); 1343 atomic_set(&dcc->issing_discard, 0); 1344 atomic_set(&dcc->discard_cmd_cnt, 0); 1345 dcc->nr_discards = 0; 1346 dcc->max_discards = 0; 1347 dcc->root = RB_ROOT; --- 1971 unchanged lines hidden --- |