summaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-rl.c
diff options
context:
space:
mode:
authorJavier González2017-04-22 01:32:49 +0200
committerJens Axboe2017-04-24 00:57:52 +0200
commita44f53faf4674d84cba79f7ee574584e18ab8744 (patch)
tree92183bdbb213a0b9604bbb387bc4749c091919cc /drivers/lightnvm/pblk-rl.c
parentlightnvm: pblk: free metadata on line alloc failure (diff)
downloadkernel-qcow2-linux-a44f53faf4674d84cba79f7ee574584e18ab8744.tar.gz
kernel-qcow2-linux-a44f53faf4674d84cba79f7ee574584e18ab8744.tar.xz
kernel-qcow2-linux-a44f53faf4674d84cba79f7ee574584e18ab8744.zip
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-rl.c')
-rw-r--r--drivers/lightnvm/pblk-rl.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c
index 4042162ec9bc..ab7cbb144f3f 100644
--- a/drivers/lightnvm/pblk-rl.c
+++ b/drivers/lightnvm/pblk-rl.c
@@ -107,9 +107,10 @@ void pblk_rl_set_gc_rsc(struct pblk_rl *rl, int rsv)
void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line)
{
struct pblk *pblk = container_of(rl, struct pblk, rl);
+ int blk_in_line = atomic_read(&line->blk_in_line);
int ret;
- atomic_add(line->blk_in_line, &rl->free_blocks);
+ atomic_add(blk_in_line, &rl->free_blocks);
/* Rates will not change that often - no need to lock update */
ret = pblk_rl_update_rates(rl, rl->rb_budget);
@@ -122,9 +123,10 @@ void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line)
void pblk_rl_free_lines_dec(struct pblk_rl *rl, struct pblk_line *line)
{
struct pblk *pblk = container_of(rl, struct pblk, rl);
+ int blk_in_line = atomic_read(&line->blk_in_line);
int ret;
- atomic_sub(line->blk_in_line, &rl->free_blocks);
+ atomic_sub(blk_in_line, &rl->free_blocks);
/* Rates will not change that often - no need to lock update */
ret = pblk_rl_update_rates(rl, rl->rb_budget);