aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-init.c
diff options
context:
space:
mode:
authorJavier González <jg@lightnvm.io>2017-04-21 19:32:49 -0400
committerJens Axboe <axboe@fb.com>2017-04-23 18:57:52 -0400
commita44f53faf4674d84cba79f7ee574584e18ab8744 (patch)
tree92183bdbb213a0b9604bbb387bc4749c091919cc /drivers/lightnvm/pblk-init.c
parentbe388d9fbd4e09582e31c3ee82a022e368208ae3 (diff)
lightnvm: pblk: fix erase counters on error fail
When block erases fail, these blocks are marked bad. The number of valid blocks in the line was not updated, which could cause an infinite loop on the erase path. Fix this atomic counter and, in order to avoid taking an irq lock on the interrupt context, make the erase counters atomic too. Also, in the case that a significant number of blocks become bad in a line, the result is the double shared metadata buffer (emeta) to stop the pipeline until all metadata is flushed to the media. Increase the number of metadata lines from 2 to 4 to avoid this case. Fixes: a4bd217b4326 "lightnvm: physical block device (pblk) target" Signed-off-by: Javier González <javier@cnexlabs.com> Reviewed-by: Matias Bjørling <matias@cnexlabs.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r--drivers/lightnvm/pblk-init.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 3996e4b8fb0e..15b2787c3ddc 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -678,6 +678,8 @@ add_emeta_page:
678 678
679 nr_free_blks = 0; 679 nr_free_blks = 0;
680 for (i = 0; i < l_mg->nr_lines; i++) { 680 for (i = 0; i < l_mg->nr_lines; i++) {
681 int blk_in_line;
682
681 line = &pblk->lines[i]; 683 line = &pblk->lines[i];
682 684
683 line->pblk = pblk; 685 line->pblk = pblk;
@@ -693,14 +695,15 @@ add_emeta_page:
693 goto fail_free_lines; 695 goto fail_free_lines;
694 } 696 }
695 697
696 line->blk_in_line = lm->blk_per_line - nr_bad_blks; 698 blk_in_line = lm->blk_per_line - nr_bad_blks;
697 if (line->blk_in_line < lm->min_blk_line) { 699 if (blk_in_line < lm->min_blk_line) {
698 line->state = PBLK_LINESTATE_BAD; 700 line->state = PBLK_LINESTATE_BAD;
699 list_add_tail(&line->list, &l_mg->bad_list); 701 list_add_tail(&line->list, &l_mg->bad_list);
700 continue; 702 continue;
701 } 703 }
702 704
703 nr_free_blks += line->blk_in_line; 705 nr_free_blks += blk_in_line;
706 atomic_set(&line->blk_in_line, blk_in_line);
704 707
705 l_mg->nr_free_lines++; 708 l_mg->nr_free_lines++;
706 list_add_tail(&line->list, &l_mg->free_list); 709 list_add_tail(&line->list, &l_mg->free_list);