aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-core.c
diff options
context:
space:
mode:
authorJavier González <jg@lightnvm.io>2017-06-26 05:57:27 -0400
committerJens Axboe <axboe@kernel.dk>2017-06-26 18:27:39 -0400
commitb20ba1bc749ce0cd7a74d24f23826a6462c3de53 (patch)
tree4a28d3558c007f5e7d27d4e24b7ed37723a16609 /drivers/lightnvm/pblk-core.c
parent476118c981f0fd909cd95a1732073120c6806ac0 (diff)
lightnvm: pblk: redesign GC algorithm
At the moment, in order to get enough read parallelism, we have recycled several lines at the same time. This approach has proven not to work well when reaching capacity, since we end up mixing valid data from all lines, thus not maintaining a sustainable free/recycled line ratio. The new design, relies on a two level workqueue mechanism. In the first level, we read the metadata for a number of lines based on the GC list they reside on (this is governed by the number of valid sectors in each line). In the second level, we recycle a single line at a time. Here, we issue reads in parallel, while a single GC write thread places data in the write buffer. This design allows to (i) only move data from one line at a time, thus maintaining a sane free/recycled ration and (ii) maintain the GC writer busy with recycled data. Signed-off-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <matias@cnexlabs.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm/pblk-core.c')
-rw-r--r--drivers/lightnvm/pblk-core.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index ed41cd7700b3..ba3b88f0e1f7 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -302,12 +302,12 @@ struct list_head *pblk_line_gc_list(struct pblk *pblk, struct pblk_line *line)
302 line->gc_group = PBLK_LINEGC_FULL; 302 line->gc_group = PBLK_LINEGC_FULL;
303 move_list = &l_mg->gc_full_list; 303 move_list = &l_mg->gc_full_list;
304 } 304 }
305 } else if (vsc < lm->mid_thrs) { 305 } else if (vsc < lm->high_thrs) {
306 if (line->gc_group != PBLK_LINEGC_HIGH) { 306 if (line->gc_group != PBLK_LINEGC_HIGH) {
307 line->gc_group = PBLK_LINEGC_HIGH; 307 line->gc_group = PBLK_LINEGC_HIGH;
308 move_list = &l_mg->gc_high_list; 308 move_list = &l_mg->gc_high_list;
309 } 309 }
310 } else if (vsc < lm->high_thrs) { 310 } else if (vsc < lm->mid_thrs) {
311 if (line->gc_group != PBLK_LINEGC_MID) { 311 if (line->gc_group != PBLK_LINEGC_MID) {
312 line->gc_group = PBLK_LINEGC_MID; 312 line->gc_group = PBLK_LINEGC_MID;
313 move_list = &l_mg->gc_mid_list; 313 move_list = &l_mg->gc_mid_list;
@@ -1199,6 +1199,7 @@ retry_get:
1199 if (pblk_line_prepare(pblk, line)) { 1199 if (pblk_line_prepare(pblk, line)) {
1200 pr_err("pblk: failed to prepare line %d\n", line->id); 1200 pr_err("pblk: failed to prepare line %d\n", line->id);
1201 list_add(&line->list, &l_mg->free_list); 1201 list_add(&line->list, &l_mg->free_list);
1202 l_mg->nr_free_lines++;
1202 return NULL; 1203 return NULL;
1203 } 1204 }
1204 1205
@@ -1465,6 +1466,8 @@ void pblk_line_close(struct pblk *pblk, struct pblk_line *line)
1465 1466
1466 spin_unlock(&line->lock); 1467 spin_unlock(&line->lock);
1467 spin_unlock(&l_mg->gc_lock); 1468 spin_unlock(&l_mg->gc_lock);
1469
1470 pblk_gc_should_kick(pblk);
1468} 1471}
1469 1472
1470void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line) 1473void pblk_line_close_meta(struct pblk *pblk, struct pblk_line *line)