summaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lightnvm/pblk-recovery.c')
-rw-r--r--drivers/lightnvm/pblk-recovery.c129
1 files changed, 48 insertions, 81 deletions
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index cb556e06673e..eadb3eb5d4dc 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -34,10 +34,6 @@ void pblk_submit_rec(struct work_struct *work)
34 max_secs); 34 max_secs);
35 35
36 bio = bio_alloc(GFP_KERNEL, nr_rec_secs); 36 bio = bio_alloc(GFP_KERNEL, nr_rec_secs);
37 if (!bio) {
38 pr_err("pblk: not able to create recovery bio\n");
39 return;
40 }
41 37
42 bio->bi_iter.bi_sector = 0; 38 bio->bi_iter.bi_sector = 0;
43 bio_set_op_attrs(bio, REQ_OP_WRITE, 0); 39 bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
@@ -71,7 +67,7 @@ void pblk_submit_rec(struct work_struct *work)
71 67
72err: 68err:
73 bio_put(bio); 69 bio_put(bio);
74 pblk_free_rqd(pblk, rqd, WRITE); 70 pblk_free_rqd(pblk, rqd, PBLK_WRITE);
75} 71}
76 72
77int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx, 73int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
@@ -84,12 +80,7 @@ int pblk_recov_setup_rq(struct pblk *pblk, struct pblk_c_ctx *c_ctx,
84 struct pblk_c_ctx *rec_ctx; 80 struct pblk_c_ctx *rec_ctx;
85 int nr_entries = c_ctx->nr_valid + c_ctx->nr_padded; 81 int nr_entries = c_ctx->nr_valid + c_ctx->nr_padded;
86 82
87 rec_rqd = pblk_alloc_rqd(pblk, WRITE); 83 rec_rqd = pblk_alloc_rqd(pblk, PBLK_WRITE);
88 if (IS_ERR(rec_rqd)) {
89 pr_err("pblk: could not create recovery req.\n");
90 return -ENOMEM;
91 }
92
93 rec_ctx = nvm_rq_to_pdu(rec_rqd); 84 rec_ctx = nvm_rq_to_pdu(rec_rqd);
94 85
95 /* Copy completion bitmap, but exclude the first X completed entries */ 86 /* Copy completion bitmap, but exclude the first X completed entries */
@@ -142,19 +133,19 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
142 struct pblk_emeta *emeta = line->emeta; 133 struct pblk_emeta *emeta = line->emeta;
143 struct line_emeta *emeta_buf = emeta->buf; 134 struct line_emeta *emeta_buf = emeta->buf;
144 __le64 *lba_list; 135 __le64 *lba_list;
145 int data_start; 136 u64 data_start, data_end;
146 int nr_data_lbas, nr_valid_lbas, nr_lbas = 0; 137 u64 nr_valid_lbas, nr_lbas = 0;
147 int i; 138 u64 i;
148 139
149 lba_list = pblk_recov_get_lba_list(pblk, emeta_buf); 140 lba_list = pblk_recov_get_lba_list(pblk, emeta_buf);
150 if (!lba_list) 141 if (!lba_list)
151 return 1; 142 return 1;
152 143
153 data_start = pblk_line_smeta_start(pblk, line) + lm->smeta_sec; 144 data_start = pblk_line_smeta_start(pblk, line) + lm->smeta_sec;
154 nr_data_lbas = lm->sec_per_line - lm->emeta_sec[0]; 145 data_end = line->emeta_ssec;
155 nr_valid_lbas = le64_to_cpu(emeta_buf->nr_valid_lbas); 146 nr_valid_lbas = le64_to_cpu(emeta_buf->nr_valid_lbas);
156 147
157 for (i = data_start; i < nr_data_lbas && nr_lbas < nr_valid_lbas; i++) { 148 for (i = data_start; i < data_end; i++) {
158 struct ppa_addr ppa; 149 struct ppa_addr ppa;
159 int pos; 150 int pos;
160 151
@@ -181,8 +172,8 @@ static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
181 } 172 }
182 173
183 if (nr_valid_lbas != nr_lbas) 174 if (nr_valid_lbas != nr_lbas)
184 pr_err("pblk: line %d - inconsistent lba list(%llu/%d)\n", 175 pr_err("pblk: line %d - inconsistent lba list(%llu/%llu)\n",
185 line->id, emeta_buf->nr_valid_lbas, nr_lbas); 176 line->id, nr_valid_lbas, nr_lbas);
186 177
187 line->left_msecs = 0; 178 line->left_msecs = 0;
188 179
@@ -225,7 +216,6 @@ static int pblk_recov_read_oob(struct pblk *pblk, struct pblk_line *line,
225 int rq_ppas, rq_len; 216 int rq_ppas, rq_len;
226 int i, j; 217 int i, j;
227 int ret = 0; 218 int ret = 0;
228 DECLARE_COMPLETION_ONSTACK(wait);
229 219
230 ppa_list = p.ppa_list; 220 ppa_list = p.ppa_list;
231 meta_list = p.meta_list; 221 meta_list = p.meta_list;
@@ -262,8 +252,6 @@ next_read_rq:
262 rqd->ppa_list = ppa_list; 252 rqd->ppa_list = ppa_list;
263 rqd->dma_ppa_list = dma_ppa_list; 253 rqd->dma_ppa_list = dma_ppa_list;
264 rqd->dma_meta_list = dma_meta_list; 254 rqd->dma_meta_list = dma_meta_list;
265 rqd->end_io = pblk_end_io_sync;
266 rqd->private = &wait;
267 255
268 if (pblk_io_aligned(pblk, rq_ppas)) 256 if (pblk_io_aligned(pblk, rq_ppas))
269 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL); 257 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
@@ -289,19 +277,13 @@ next_read_rq:
289 } 277 }
290 278
291 /* If read fails, more padding is needed */ 279 /* If read fails, more padding is needed */
292 ret = pblk_submit_io(pblk, rqd); 280 ret = pblk_submit_io_sync(pblk, rqd);
293 if (ret) { 281 if (ret) {
294 pr_err("pblk: I/O submission failed: %d\n", ret); 282 pr_err("pblk: I/O submission failed: %d\n", ret);
295 return ret; 283 return ret;
296 } 284 }
297 285
298 if (!wait_for_completion_io_timeout(&wait,
299 msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
300 pr_err("pblk: L2P recovery read timed out\n");
301 return -EINTR;
302 }
303 atomic_dec(&pblk->inflight_io); 286 atomic_dec(&pblk->inflight_io);
304 reinit_completion(&wait);
305 287
306 /* At this point, the read should not fail. If it does, it is a problem 288 /* At this point, the read should not fail. If it does, it is a problem
307 * we cannot recover from here. Need FTL log. 289 * we cannot recover from here. Need FTL log.
@@ -338,13 +320,10 @@ static void pblk_end_io_recov(struct nvm_rq *rqd)
338{ 320{
339 struct pblk_pad_rq *pad_rq = rqd->private; 321 struct pblk_pad_rq *pad_rq = rqd->private;
340 struct pblk *pblk = pad_rq->pblk; 322 struct pblk *pblk = pad_rq->pblk;
341 struct nvm_tgt_dev *dev = pblk->dev;
342 323
343 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas); 324 pblk_up_page(pblk, rqd->ppa_list, rqd->nr_ppas);
344 325
345 bio_put(rqd->bio); 326 pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
346 nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
347 pblk_free_rqd(pblk, rqd, WRITE);
348 327
349 atomic_dec(&pblk->inflight_io); 328 atomic_dec(&pblk->inflight_io);
350 kref_put(&pad_rq->ref, pblk_recov_complete); 329 kref_put(&pad_rq->ref, pblk_recov_complete);
@@ -404,25 +383,21 @@ next_pad_rq:
404 ppa_list = (void *)(meta_list) + pblk_dma_meta_size; 383 ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
405 dma_ppa_list = dma_meta_list + pblk_dma_meta_size; 384 dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
406 385
407 rqd = pblk_alloc_rqd(pblk, WRITE);
408 if (IS_ERR(rqd)) {
409 ret = PTR_ERR(rqd);
410 goto fail_free_meta;
411 }
412
413 bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len, 386 bio = pblk_bio_map_addr(pblk, data, rq_ppas, rq_len,
414 PBLK_VMALLOC_META, GFP_KERNEL); 387 PBLK_VMALLOC_META, GFP_KERNEL);
415 if (IS_ERR(bio)) { 388 if (IS_ERR(bio)) {
416 ret = PTR_ERR(bio); 389 ret = PTR_ERR(bio);
417 goto fail_free_rqd; 390 goto fail_free_meta;
418 } 391 }
419 392
420 bio->bi_iter.bi_sector = 0; /* internal bio */ 393 bio->bi_iter.bi_sector = 0; /* internal bio */
421 bio_set_op_attrs(bio, REQ_OP_WRITE, 0); 394 bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
422 395
396 rqd = pblk_alloc_rqd(pblk, PBLK_WRITE_INT);
397
423 rqd->bio = bio; 398 rqd->bio = bio;
424 rqd->opcode = NVM_OP_PWRITE; 399 rqd->opcode = NVM_OP_PWRITE;
425 rqd->flags = pblk_set_progr_mode(pblk, WRITE); 400 rqd->flags = pblk_set_progr_mode(pblk, PBLK_WRITE);
426 rqd->meta_list = meta_list; 401 rqd->meta_list = meta_list;
427 rqd->nr_ppas = rq_ppas; 402 rqd->nr_ppas = rq_ppas;
428 rqd->ppa_list = ppa_list; 403 rqd->ppa_list = ppa_list;
@@ -490,8 +465,6 @@ free_rq:
490 465
491fail_free_bio: 466fail_free_bio:
492 bio_put(bio); 467 bio_put(bio);
493fail_free_rqd:
494 pblk_free_rqd(pblk, rqd, WRITE);
495fail_free_meta: 468fail_free_meta:
496 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list); 469 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list);
497fail_free_pad: 470fail_free_pad:
@@ -522,7 +495,6 @@ static int pblk_recov_scan_all_oob(struct pblk *pblk, struct pblk_line *line,
522 int ret = 0; 495 int ret = 0;
523 int rec_round; 496 int rec_round;
524 int left_ppas = pblk_calc_sec_in_line(pblk, line) - line->cur_sec; 497 int left_ppas = pblk_calc_sec_in_line(pblk, line) - line->cur_sec;
525 DECLARE_COMPLETION_ONSTACK(wait);
526 498
527 ppa_list = p.ppa_list; 499 ppa_list = p.ppa_list;
528 meta_list = p.meta_list; 500 meta_list = p.meta_list;
@@ -557,8 +529,6 @@ next_rq:
557 rqd->ppa_list = ppa_list; 529 rqd->ppa_list = ppa_list;
558 rqd->dma_ppa_list = dma_ppa_list; 530 rqd->dma_ppa_list = dma_ppa_list;
559 rqd->dma_meta_list = dma_meta_list; 531 rqd->dma_meta_list = dma_meta_list;
560 rqd->end_io = pblk_end_io_sync;
561 rqd->private = &wait;
562 532
563 if (pblk_io_aligned(pblk, rq_ppas)) 533 if (pblk_io_aligned(pblk, rq_ppas))
564 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL); 534 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
@@ -584,18 +554,13 @@ next_rq:
584 addr_to_gen_ppa(pblk, w_ptr, line->id); 554 addr_to_gen_ppa(pblk, w_ptr, line->id);
585 } 555 }
586 556
587 ret = pblk_submit_io(pblk, rqd); 557 ret = pblk_submit_io_sync(pblk, rqd);
588 if (ret) { 558 if (ret) {
589 pr_err("pblk: I/O submission failed: %d\n", ret); 559 pr_err("pblk: I/O submission failed: %d\n", ret);
590 return ret; 560 return ret;
591 } 561 }
592 562
593 if (!wait_for_completion_io_timeout(&wait,
594 msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
595 pr_err("pblk: L2P recovery read timed out\n");
596 }
597 atomic_dec(&pblk->inflight_io); 563 atomic_dec(&pblk->inflight_io);
598 reinit_completion(&wait);
599 564
600 /* This should not happen since the read failed during normal recovery, 565 /* This should not happen since the read failed during normal recovery,
601 * but the media works funny sometimes... 566 * but the media works funny sometimes...
@@ -663,7 +628,6 @@ static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
663 int i, j; 628 int i, j;
664 int ret = 0; 629 int ret = 0;
665 int left_ppas = pblk_calc_sec_in_line(pblk, line); 630 int left_ppas = pblk_calc_sec_in_line(pblk, line);
666 DECLARE_COMPLETION_ONSTACK(wait);
667 631
668 ppa_list = p.ppa_list; 632 ppa_list = p.ppa_list;
669 meta_list = p.meta_list; 633 meta_list = p.meta_list;
@@ -696,8 +660,6 @@ next_rq:
696 rqd->ppa_list = ppa_list; 660 rqd->ppa_list = ppa_list;
697 rqd->dma_ppa_list = dma_ppa_list; 661 rqd->dma_ppa_list = dma_ppa_list;
698 rqd->dma_meta_list = dma_meta_list; 662 rqd->dma_meta_list = dma_meta_list;
699 rqd->end_io = pblk_end_io_sync;
700 rqd->private = &wait;
701 663
702 if (pblk_io_aligned(pblk, rq_ppas)) 664 if (pblk_io_aligned(pblk, rq_ppas))
703 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL); 665 rqd->flags = pblk_set_read_mode(pblk, PBLK_READ_SEQUENTIAL);
@@ -723,19 +685,14 @@ next_rq:
723 addr_to_gen_ppa(pblk, paddr, line->id); 685 addr_to_gen_ppa(pblk, paddr, line->id);
724 } 686 }
725 687
726 ret = pblk_submit_io(pblk, rqd); 688 ret = pblk_submit_io_sync(pblk, rqd);
727 if (ret) { 689 if (ret) {
728 pr_err("pblk: I/O submission failed: %d\n", ret); 690 pr_err("pblk: I/O submission failed: %d\n", ret);
729 bio_put(bio); 691 bio_put(bio);
730 return ret; 692 return ret;
731 } 693 }
732 694
733 if (!wait_for_completion_io_timeout(&wait,
734 msecs_to_jiffies(PBLK_COMMAND_TIMEOUT_MS))) {
735 pr_err("pblk: L2P recovery read timed out\n");
736 }
737 atomic_dec(&pblk->inflight_io); 695 atomic_dec(&pblk->inflight_io);
738 reinit_completion(&wait);
739 696
740 /* Reached the end of the written line */ 697 /* Reached the end of the written line */
741 if (rqd->error) { 698 if (rqd->error) {
@@ -785,15 +742,9 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
785 dma_addr_t dma_ppa_list, dma_meta_list; 742 dma_addr_t dma_ppa_list, dma_meta_list;
786 int done, ret = 0; 743 int done, ret = 0;
787 744
788 rqd = pblk_alloc_rqd(pblk, READ);
789 if (IS_ERR(rqd))
790 return PTR_ERR(rqd);
791
792 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list); 745 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, &dma_meta_list);
793 if (!meta_list) { 746 if (!meta_list)
794 ret = -ENOMEM; 747 return -ENOMEM;
795 goto free_rqd;
796 }
797 748
798 ppa_list = (void *)(meta_list) + pblk_dma_meta_size; 749 ppa_list = (void *)(meta_list) + pblk_dma_meta_size;
799 dma_ppa_list = dma_meta_list + pblk_dma_meta_size; 750 dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
@@ -804,6 +755,8 @@ static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
804 goto free_meta_list; 755 goto free_meta_list;
805 } 756 }
806 757
758 rqd = pblk_alloc_rqd(pblk, PBLK_READ);
759
807 p.ppa_list = ppa_list; 760 p.ppa_list = ppa_list;
808 p.meta_list = meta_list; 761 p.meta_list = meta_list;
809 p.rqd = rqd; 762 p.rqd = rqd;
@@ -832,8 +785,6 @@ out:
832 kfree(data); 785 kfree(data);
833free_meta_list: 786free_meta_list:
834 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list); 787 nvm_dev_dma_free(dev->parent, meta_list, dma_meta_list);
835free_rqd:
836 pblk_free_rqd(pblk, rqd, READ);
837 788
838 return ret; 789 return ret;
839} 790}
@@ -851,11 +802,33 @@ static void pblk_recov_line_add_ordered(struct list_head *head,
851 __list_add(&line->list, t->list.prev, &t->list); 802 __list_add(&line->list, t->list.prev, &t->list);
852} 803}
853 804
854struct pblk_line *pblk_recov_l2p(struct pblk *pblk) 805static u64 pblk_line_emeta_start(struct pblk *pblk, struct pblk_line *line)
855{ 806{
856 struct nvm_tgt_dev *dev = pblk->dev; 807 struct nvm_tgt_dev *dev = pblk->dev;
857 struct nvm_geo *geo = &dev->geo; 808 struct nvm_geo *geo = &dev->geo;
858 struct pblk_line_meta *lm = &pblk->lm; 809 struct pblk_line_meta *lm = &pblk->lm;
810 unsigned int emeta_secs;
811 u64 emeta_start;
812 struct ppa_addr ppa;
813 int pos;
814
815 emeta_secs = lm->emeta_sec[0];
816 emeta_start = lm->sec_per_line;
817
818 while (emeta_secs) {
819 emeta_start--;
820 ppa = addr_to_pblk_ppa(pblk, emeta_start, line->id);
821 pos = pblk_ppa_to_pos(geo, ppa);
822 if (!test_bit(pos, line->blk_bitmap))
823 emeta_secs--;
824 }
825
826 return emeta_start;
827}
828
829struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
830{
831 struct pblk_line_meta *lm = &pblk->lm;
859 struct pblk_line_mgmt *l_mg = &pblk->l_mg; 832 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
860 struct pblk_line *line, *tline, *data_line = NULL; 833 struct pblk_line *line, *tline, *data_line = NULL;
861 struct pblk_smeta *smeta; 834 struct pblk_smeta *smeta;
@@ -900,9 +873,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
900 if (le32_to_cpu(smeta_buf->header.identifier) != PBLK_MAGIC) 873 if (le32_to_cpu(smeta_buf->header.identifier) != PBLK_MAGIC)
901 continue; 874 continue;
902 875
903 if (le16_to_cpu(smeta_buf->header.version) != 1) { 876 if (smeta_buf->header.version != SMETA_VERSION) {
904 pr_err("pblk: found incompatible line version %u\n", 877 pr_err("pblk: found incompatible line version %u\n",
905 smeta_buf->header.version); 878 le16_to_cpu(smeta_buf->header.version));
906 return ERR_PTR(-EINVAL); 879 return ERR_PTR(-EINVAL);
907 } 880 }
908 881
@@ -954,15 +927,9 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
954 927
955 /* Verify closed blocks and recover this portion of L2P table*/ 928 /* Verify closed blocks and recover this portion of L2P table*/
956 list_for_each_entry_safe(line, tline, &recov_list, list) { 929 list_for_each_entry_safe(line, tline, &recov_list, list) {
957 int off, nr_bb;
958
959 recovered_lines++; 930 recovered_lines++;
960 /* Calculate where emeta starts based on the line bb */
961 off = lm->sec_per_line - lm->emeta_sec[0];
962 nr_bb = bitmap_weight(line->blk_bitmap, lm->blk_per_line);
963 off -= nr_bb * geo->sec_per_pl;
964 931
965 line->emeta_ssec = off; 932 line->emeta_ssec = pblk_line_emeta_start(pblk, line);
966 line->emeta = emeta; 933 line->emeta = emeta;
967 memset(line->emeta->buf, 0, lm->emeta_len[0]); 934 memset(line->emeta->buf, 0, lm->emeta_len[0]);
968 935
@@ -987,7 +954,7 @@ next:
987 list_move_tail(&line->list, move_list); 954 list_move_tail(&line->list, move_list);
988 spin_unlock(&l_mg->gc_lock); 955 spin_unlock(&l_mg->gc_lock);
989 956
990 mempool_free(line->map_bitmap, pblk->line_meta_pool); 957 kfree(line->map_bitmap);
991 line->map_bitmap = NULL; 958 line->map_bitmap = NULL;
992 line->smeta = NULL; 959 line->smeta = NULL;
993 line->emeta = NULL; 960 line->emeta = NULL;