aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/rrpc.c
diff options
context:
space:
mode:
authorWenwei Tao <ww.tao0320@gmail.com>2016-01-12 07:49:24 +0100
committerJens Axboe <axboe@fb.com>2016-01-12 08:21:16 -0700
commitd0ca798f960ad7d86f5186fe312c131d00563eb7 (patch)
tree2900e3849549171ec2914539c7ebb9a3b4554db3 /drivers/lightnvm/rrpc.c
parentlightnvm: check bi_error in gc (diff)
downloadlinux-dev-d0ca798f960ad7d86f5186fe312c131d00563eb7.tar.xz
linux-dev-d0ca798f960ad7d86f5186fe312c131d00563eb7.zip
lightnvm: put block back to gc list on its reclaim fail
We delete a block from the gc list before reclaim it, so put it back to the list on its reclaim fail, otherwise this block will not get reclaimed and be programmable in the future. Signed-off-by: Wenwei Tao <ww.tao0320@gmail.com> Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm/rrpc.c')
-rw-r--r--drivers/lightnvm/rrpc.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
index 5df4a696184a..bee2352fcce1 100644
--- a/drivers/lightnvm/rrpc.c
+++ b/drivers/lightnvm/rrpc.c
@@ -381,16 +381,26 @@ static void rrpc_block_gc(struct work_struct *work)
struct rrpc *rrpc = gcb->rrpc;
struct rrpc_block *rblk = gcb->rblk;
struct nvm_dev *dev = rrpc->dev;
+ struct nvm_lun *lun = rblk->parent->lun;
+ struct rrpc_lun *rlun = &rrpc->luns[lun->id - rrpc->lun_offset];
+ mempool_free(gcb, rrpc->gcb_pool);
pr_debug("nvm: block '%lu' being reclaimed\n", rblk->parent->id);
if (rrpc_move_valid_pages(rrpc, rblk))
- goto done;
+ goto put_back;
+
+ if (nvm_erase_blk(dev, rblk->parent))
+ goto put_back;
- nvm_erase_blk(dev, rblk->parent);
rrpc_put_blk(rrpc, rblk);
-done:
- mempool_free(gcb, rrpc->gcb_pool);
+
+ return;
+
+put_back:
+ spin_lock(&rlun->lock);
+ list_add_tail(&rblk->prio, &rlun->prio_list);
+ spin_unlock(&rlun->lock);
}
/* the block with highest number of invalid pages, will be in the beginning