aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-core.c
diff options
context:
space:
mode:
authorJavier González <javier@cnexlabs.com>2017-10-13 08:46:23 -0400
committerJens Axboe <axboe@kernel.dk>2017-10-13 10:34:57 -0400
commit7bd4d370db6090004a06deb526f0f01fa99a3f9f (patch)
tree01cbfeca78132835d73f56f1a42c5aeb0731b287 /drivers/lightnvm/pblk-core.c
parenta4809fee4e774fdf3296cc69c22ce6e6acef36b2 (diff)
lightnvm: pblk: guarantee line integrity on reads
When a line is recycled during garbage collection, reads can still be issued to the line. If the line is freed in the middle of this process, data corruption might occur. This patch guarantees that lines are not freed in the middle of reads that target them (lines). Specifically, we use the existing line reference to decide when a line is eligible for being freed after the recycle process. Signed-off-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm/pblk-core.c')
-rw-r--r--drivers/lightnvm/pblk-core.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 08d166ac4f3c..0a41fb998d55 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1460,10 +1460,8 @@ void pblk_line_free(struct pblk *pblk, struct pblk_line *line)
1460 line->emeta = NULL; 1460 line->emeta = NULL;
1461} 1461}
1462 1462
1463void pblk_line_put(struct kref *ref) 1463static void __pblk_line_put(struct pblk *pblk, struct pblk_line *line)
1464{ 1464{
1465 struct pblk_line *line = container_of(ref, struct pblk_line, ref);
1466 struct pblk *pblk = line->pblk;
1467 struct pblk_line_mgmt *l_mg = &pblk->l_mg; 1465 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
1468 1466
1469 spin_lock(&line->lock); 1467 spin_lock(&line->lock);
@@ -1481,6 +1479,43 @@ void pblk_line_put(struct kref *ref)
1481 pblk_rl_free_lines_inc(&pblk->rl, line); 1479 pblk_rl_free_lines_inc(&pblk->rl, line);
1482} 1480}
1483 1481
1482static void pblk_line_put_ws(struct work_struct *work)
1483{
1484 struct pblk_line_ws *line_put_ws = container_of(work,
1485 struct pblk_line_ws, ws);
1486 struct pblk *pblk = line_put_ws->pblk;
1487 struct pblk_line *line = line_put_ws->line;
1488
1489 __pblk_line_put(pblk, line);
1490 mempool_free(line_put_ws, pblk->gen_ws_pool);
1491}
1492
1493void pblk_line_put(struct kref *ref)
1494{
1495 struct pblk_line *line = container_of(ref, struct pblk_line, ref);
1496 struct pblk *pblk = line->pblk;
1497
1498 __pblk_line_put(pblk, line);
1499}
1500
1501void pblk_line_put_wq(struct kref *ref)
1502{
1503 struct pblk_line *line = container_of(ref, struct pblk_line, ref);
1504 struct pblk *pblk = line->pblk;
1505 struct pblk_line_ws *line_put_ws;
1506
1507 line_put_ws = mempool_alloc(pblk->gen_ws_pool, GFP_ATOMIC);
1508 if (!line_put_ws)
1509 return;
1510
1511 line_put_ws->pblk = pblk;
1512 line_put_ws->line = line;
1513 line_put_ws->priv = NULL;
1514
1515 INIT_WORK(&line_put_ws->ws, pblk_line_put_ws);
1516 queue_work(pblk->r_end_wq, &line_put_ws->ws);
1517}
1518
1484int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa) 1519int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr ppa)
1485{ 1520{
1486 struct nvm_rq *rqd; 1521 struct nvm_rq *rqd;
@@ -1878,8 +1913,19 @@ void pblk_lookup_l2p_seq(struct pblk *pblk, struct ppa_addr *ppas,
1878 int i; 1913 int i;
1879 1914
1880 spin_lock(&pblk->trans_lock); 1915 spin_lock(&pblk->trans_lock);
1881 for (i = 0; i < nr_secs; i++) 1916 for (i = 0; i < nr_secs; i++) {
1882 ppas[i] = pblk_trans_map_get(pblk, blba + i); 1917 struct ppa_addr ppa;
1918
1919 ppa = ppas[i] = pblk_trans_map_get(pblk, blba + i);
1920
1921 /* If the L2P entry maps to a line, the reference is valid */
1922 if (!pblk_ppa_empty(ppa) && !pblk_addr_in_cache(ppa)) {
1923 int line_id = pblk_dev_ppa_to_line(ppa);
1924 struct pblk_line *line = &pblk->lines[line_id];
1925
1926 kref_get(&line->ref);
1927 }
1928 }
1883 spin_unlock(&pblk->trans_lock); 1929 spin_unlock(&pblk->trans_lock);
1884} 1930}
1885 1931