aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier González <jg@lightnvm.io>2017-07-07 15:08:52 -0400
committerJens Axboe <axboe@kernel.dk>2017-07-07 15:17:34 -0400
commit3eaa11e2780dc38350c133bd998cac1df488d040 (patch)
tree72f51ca76c7ae028386bd614220faf97d56b1cfd
parent0e2ff11311d1d4c85dd9ad9ba4347775f628e94a (diff)
lightnvm: pblk: control I/O flow also on tear down
When removing a pblk instance, control the write I/O flow to the controller as we do in the fast path. 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>
-rw-r--r--drivers/lightnvm/pblk-core.c61
-rw-r--r--drivers/lightnvm/pblk-recovery.c31
-rw-r--r--drivers/lightnvm/pblk-write.c19
-rw-r--r--drivers/lightnvm/pblk.h2
4 files changed, 78 insertions, 35 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 11fe0c5b2a9c..81501644fb15 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -1670,13 +1670,10 @@ void pblk_line_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,
1670 queue_work(wq, &line_ws->ws); 1670 queue_work(wq, &line_ws->ws);
1671} 1671}
1672 1672
1673void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, 1673static void __pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list,
1674 unsigned long *lun_bitmap) 1674 int nr_ppas, int pos)
1675{ 1675{
1676 struct nvm_tgt_dev *dev = pblk->dev; 1676 struct pblk_lun *rlun = &pblk->luns[pos];
1677 struct nvm_geo *geo = &dev->geo;
1678 struct pblk_lun *rlun;
1679 int pos = pblk_ppa_to_pos(geo, ppa_list[0]);
1680 int ret; 1677 int ret;
1681 1678
1682 /* 1679 /*
@@ -1690,14 +1687,8 @@ void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
1690 WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun || 1687 WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
1691 ppa_list[0].g.ch != ppa_list[i].g.ch); 1688 ppa_list[0].g.ch != ppa_list[i].g.ch);
1692#endif 1689#endif
1693 /* If the LUN has been locked for this same request, do no attempt to
1694 * lock it again
1695 */
1696 if (test_and_set_bit(pos, lun_bitmap))
1697 return;
1698 1690
1699 rlun = &pblk->luns[pos]; 1691 ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(30000));
1700 ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(5000));
1701 if (ret) { 1692 if (ret) {
1702 switch (ret) { 1693 switch (ret) {
1703 case -ETIME: 1694 case -ETIME:
@@ -1710,6 +1701,50 @@ void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
1710 } 1701 }
1711} 1702}
1712 1703
1704void pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas)
1705{
1706 struct nvm_tgt_dev *dev = pblk->dev;
1707 struct nvm_geo *geo = &dev->geo;
1708 int pos = pblk_ppa_to_pos(geo, ppa_list[0]);
1709
1710 __pblk_down_page(pblk, ppa_list, nr_ppas, pos);
1711}
1712
1713void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
1714 unsigned long *lun_bitmap)
1715{
1716 struct nvm_tgt_dev *dev = pblk->dev;
1717 struct nvm_geo *geo = &dev->geo;
1718 int pos = pblk_ppa_to_pos(geo, ppa_list[0]);
1719
1720 /* If the LUN has been locked for this same request, do no attempt to
1721 * lock it again
1722 */
1723 if (test_and_set_bit(pos, lun_bitmap))
1724 return;
1725
1726 __pblk_down_page(pblk, ppa_list, nr_ppas, pos);
1727}
1728
1729void pblk_up_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas)
1730{
1731 struct nvm_tgt_dev *dev = pblk->dev;
1732 struct nvm_geo *geo = &dev->geo;
1733 struct pblk_lun *rlun;
1734 int pos = pblk_ppa_to_pos(geo, ppa_list[0]);
1735
1736#ifdef CONFIG_NVM_DEBUG
1737 int i;
1738
1739 for (i = 1; i < nr_ppas; i++)
1740 WARN_ON(ppa_list[0].g.lun != ppa_list[i].g.lun ||
1741 ppa_list[0].g.ch != ppa_list[i].g.ch);
1742#endif
1743
1744 rlun = &pblk->luns[pos];
1745 up(&rlun->wr_sem);
1746}
1747
1713void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, 1748void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
1714 unsigned long *lun_bitmap) 1749 unsigned long *lun_bitmap)
1715{ 1750{
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index 0e48d3e4e143..cb556e06673e 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -340,9 +340,14 @@ static void pblk_end_io_recov(struct nvm_rq *rqd)
340 struct pblk *pblk = pad_rq->pblk; 340 struct pblk *pblk = pad_rq->pblk;
341 struct nvm_tgt_dev *dev = pblk->dev; 341 struct nvm_tgt_dev *dev = pblk->dev;
342 342
343 kref_put(&pad_rq->ref, pblk_recov_complete); 343 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
344
345 bio_put(rqd->bio);
344 nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list); 346 nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
345 pblk_free_rqd(pblk, rqd, WRITE); 347 pblk_free_rqd(pblk, rqd, WRITE);
348
349 atomic_dec(&pblk->inflight_io);
350 kref_put(&pad_rq->ref, pblk_recov_complete);
346} 351}
347 352
348static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line, 353static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
@@ -385,7 +390,7 @@ next_pad_rq:
385 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0); 390 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
386 if (rq_ppas < pblk->min_write_pgs) { 391 if (rq_ppas < pblk->min_write_pgs) {
387 pr_err("pblk: corrupted pad line %d\n", line->id); 392 pr_err("pblk: corrupted pad line %d\n", line->id);
388 goto free_rq; 393 goto fail_free_pad;
389 } 394 }
390 395
391 rq_len = rq_ppas * geo->sec_size; 396 rq_len = rq_ppas * geo->sec_size;
@@ -393,7 +398,7 @@ next_pad_rq:
393 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list); 398 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
394 if (!meta_list) { 399 if (!meta_list) {
395 ret = -ENOMEM; 400 ret = -ENOMEM;
396 goto free_data; 401 goto fail_free_pad;
397 } 402 }
398 403
399 ppa_list = (void *)(meta_list) + pblk_dma_meta_size; 404 ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
@@ -404,9 +409,9 @@ next_pad_rq:
404 ret = PTR_ERR(rqd); 409 ret = PTR_ERR(rqd);
405 goto fail_free_meta; 410 goto fail_free_meta;
406 } 411 }
407 memset(rqd, 0, pblk_w_rq_size);
408 412
409 bio = bio_map_kern(dev->q, data, rq_len, GFP_KERNEL); 413 bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
414 PBLK_VMALLOC_META, GFP_KERNEL);
410 if (IS_ERR(bio)) { 415 if (IS_ERR(bio)) {
411 ret = PTR_ERR(bio); 416 ret = PTR_ERR(bio);
412 goto fail_free_rqd; 417 goto fail_free_rqd;
@@ -453,15 +458,15 @@ next_pad_rq:
453 } 458 }
454 459
455 kref_get(&pad_rq->ref); 460 kref_get(&pad_rq->ref);
461 pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas);
456 462
457 ret = pblk_submit_io(pblk, rqd); 463 ret = pblk_submit_io(pblk, rqd);
458 if (ret) { 464 if (ret) {
459 pr_err("pblk: I/O submission failed: %d\n", ret); 465 pr_err("pblk: I/O submission failed: %d\n", ret);
460 goto free_data; 466 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
467 goto fail_free_bio;
461 } 468 }
462 469
463 atomic_dec(&pblk->inflight_io);
464
465 left_line_ppas -= rq_ppas; 470 left_line_ppas -= rq_ppas;
466 left_ppas -= rq_ppas; 471 left_ppas -= rq_ppas;
467 if (left_ppas && left_line_ppas) 472 if (left_ppas && left_line_ppas)
@@ -475,17 +480,23 @@ next_pad_rq:
475 ret = -ETIME; 480 ret = -ETIME;
476 } 481 }
477 482
483 if (!pblk_line_is_full(line))
484 pr_err("pblk: corrupted padded line: %d\n", line->id);
485
486 vfree(data);
478free_rq: 487free_rq:
479 kfree(pad_rq); 488 kfree(pad_rq);
480free_data:
481 vfree(data);
482 return ret; 489 return ret;
483 490
491fail_free_bio:
492 bio_put(bio);
484fail_free_rqd: 493fail_free_rqd:
485 pblk_free_rqd(pblk, rqd, WRITE); 494 pblk_free_rqd(pblk, rqd, WRITE);
486fail_free_meta: 495fail_free_meta:
487 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list); 496 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list);
497fail_free_pad:
488 kfree(pad_rq); 498 kfree(pad_rq);
499 vfree(data);
489 return ret; 500 return ret;
490} 501}
491 502
diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
index d62a8f4faaf4..cc2b9414d17c 100644
--- a/drivers/lightnvm/pblk-write.c
+++ b/drivers/lightnvm/pblk-write.c
@@ -178,15 +178,12 @@ static void pblk_end_io_write_meta(struct nvm_rq *rqd)
178{ 178{
179 struct pblk *pblk = rqd->private; 179 struct pblk *pblk = rqd->private;
180 struct nvm_tgt_dev *dev = pblk->dev; 180 struct nvm_tgt_dev *dev = pblk->dev;
181 struct nvm_geo *geo = &dev->geo;
182 struct pblk_g_ctx *m_ctx = nvm_rq_to_pdu(rqd); 181 struct pblk_g_ctx *m_ctx = nvm_rq_to_pdu(rqd);
183 struct pblk_line *line = m_ctx->private; 182 struct pblk_line *line = m_ctx->private;
184 struct pblk_emeta *emeta = line->emeta; 183 struct pblk_emeta *emeta = line->emeta;
185 int pos = pblk_ppa_to_pos(geo, rqd->ppa_list[0]);
186 struct pblk_lun *rlun = &pblk->luns[pos];
187 int sync; 184 int sync;
188 185
189 up(&rlun->wr_sem); 186 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
190 187
191 if (rqd->error) { 188 if (rqd->error) {
192 pblk_log_write_err(pblk, rqd); 189 pblk_log_write_err(pblk, rqd);
@@ -203,6 +200,7 @@ static void pblk_end_io_write_meta(struct nvm_rq *rqd)
203 pblk->close_wq); 200 pblk->close_wq);
204 201
205 bio_put(rqd->bio); 202 bio_put(rqd->bio);
203 nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
206 pblk_free_rqd(pblk, rqd, READ); 204 pblk_free_rqd(pblk, rqd, READ);
207 205
208 atomic_dec(&pblk->inflight_io); 206 atomic_dec(&pblk->inflight_io);
@@ -367,7 +365,6 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
367 struct pblk_line_meta *lm = &pblk->lm; 365 struct pblk_line_meta *lm = &pblk->lm;
368 struct pblk_emeta *emeta = meta_line->emeta; 366 struct pblk_emeta *emeta = meta_line->emeta;
369 struct pblk_g_ctx *m_ctx; 367 struct pblk_g_ctx *m_ctx;
370 struct pblk_lun *rlun;
371 struct bio *bio; 368 struct bio *bio;
372 struct nvm_rq *rqd; 369 struct nvm_rq *rqd;
373 void *data; 370 void *data;
@@ -411,13 +408,6 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
411 rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id); 408 rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id);
412 } 409 }
413 410
414 rlun = &pblk->luns[pblk_ppa_to_pos(geo, rqd->ppa_list[0])];
415 ret = down_timeout(&rlun->wr_sem, msecs_to_jiffies(5000));
416 if (ret) {
417 pr_err("pblk: lun semaphore timed out (%d)\n", ret);
418 goto fail_free_bio;
419 }
420
421 emeta->mem += rq_len; 411 emeta->mem += rq_len;
422 if (emeta->mem >= lm->emeta_len[0]) { 412 if (emeta->mem >= lm->emeta_len[0]) {
423 spin_lock(&l_mg->close_lock); 413 spin_lock(&l_mg->close_lock);
@@ -427,6 +417,8 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
427 spin_unlock(&l_mg->close_lock); 417 spin_unlock(&l_mg->close_lock);
428 } 418 }
429 419
420 pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas);
421
430 ret = pblk_submit_io(pblk, rqd); 422 ret = pblk_submit_io(pblk, rqd);
431 if (ret) { 423 if (ret) {
432 pr_err("pblk: emeta I/O submission failed: %d\n", ret); 424 pr_err("pblk: emeta I/O submission failed: %d\n", ret);
@@ -436,10 +428,13 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line)
436 return NVM_IO_OK; 428 return NVM_IO_OK;
437 429
438fail_rollback: 430fail_rollback:
431 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
439 spin_lock(&l_mg->close_lock); 432 spin_lock(&l_mg->close_lock);
440 pblk_dealloc_page(pblk, meta_line, rq_ppas); 433 pblk_dealloc_page(pblk, meta_line, rq_ppas);
441 list_add(&meta_line->list, &meta_line->list); 434 list_add(&meta_line->list, &meta_line->list);
442 spin_unlock(&l_mg->close_lock); 435 spin_unlock(&l_mg->close_lock);
436
437 nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
443fail_free_bio: 438fail_free_bio:
444 if (likely(l_mg->emeta_alloc_type == PBLK_VMALLOC_META)) 439 if (likely(l_mg->emeta_alloc_type == PBLK_VMALLOC_META))
445 bio_put(bio); 440 bio_put(bio);
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 15931381348c..0c5692cc2f60 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -739,8 +739,10 @@ u64 pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);
739u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs); 739u64 __pblk_alloc_page(struct pblk *pblk, struct pblk_line *line, int nr_secs);
740int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail, 740int pblk_calc_secs(struct pblk *pblk, unsigned long secs_avail,
741 unsigned long secs_to_flush); 741 unsigned long secs_to_flush);
742void pblk_up_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas);
742void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, 743void pblk_down_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
743 unsigned long *lun_bitmap); 744 unsigned long *lun_bitmap);
745void pblk_down_page(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas);
744void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas, 746void pblk_up_rq(struct pblk *pblk, struct ppa_addr *ppa_list, int nr_ppas,
745 unsigned long *lun_bitmap); 747 unsigned long *lun_bitmap);
746void pblk_end_bio_sync(struct bio *bio); 748void pblk_end_bio_sync(struct bio *bio);