aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm
diff options
context:
space:
mode:
authorJavier González <javier@javigon.com>2018-10-09 07:12:03 -0400
committerJens Axboe <axboe@kernel.dk>2018-10-09 10:25:07 -0400
commitaf3fac1664b978f70a838571f3f35298ce1786da (patch)
treecdcd70a45e2e2b5bb71d2bdf0d2f7e01d8cc926f /drivers/lightnvm
parent45dcf29b98377bbdc40aa4a23a79ade60295dbaf (diff)
lightnvm: pblk: refactor metadata paths
pblk maintains two different metadata paths for smeta and emeta, which store metadata at the start of the line and at the end of the line, respectively. Until now, these path has been common for writing and retrieving metadata, however, as these paths diverge, the common code becomes less clear and unnecessary complicated. In preparation for further changes to the metadata write path, this patch separates the write and read paths for smeta and emeta and removes the synchronous emeta path as it not used anymore (emeta is scheduled asynchronously to prevent jittering due to internal I/Os). Signed-off-by: Javier González <javier@cnexlabs.com> Signed-off-by: Matias Bjørling <mb@lightnvm.io> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/lightnvm')
-rw-r--r--drivers/lightnvm/pblk-core.c307
-rw-r--r--drivers/lightnvm/pblk-gc.c2
-rw-r--r--drivers/lightnvm/pblk-recovery.c4
-rw-r--r--drivers/lightnvm/pblk.h4
4 files changed, 146 insertions, 171 deletions
diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
index 8ae40855d4c9..49cef93e328e 100644
--- a/drivers/lightnvm/pblk-core.c
+++ b/drivers/lightnvm/pblk-core.c
@@ -685,180 +685,80 @@ u64 pblk_lookup_page(struct pblk *pblk, struct pblk_line *line)
685 return paddr; 685 return paddr;
686} 686}
687 687
688/* 688u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line)
689 * Submit emeta to one LUN in the raid line at the time to avoid a deadlock when
690 * taking the per LUN semaphore.
691 */
692static int pblk_line_submit_emeta_io(struct pblk *pblk, struct pblk_line *line,
693 void *emeta_buf, u64 paddr, int dir)
694{ 689{
695 struct nvm_tgt_dev *dev = pblk->dev; 690 struct nvm_tgt_dev *dev = pblk->dev;
696 struct nvm_geo *geo = &dev->geo; 691 struct nvm_geo *geo = &dev->geo;
697 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
698 struct pblk_line_meta *lm = &pblk->lm; 692 struct pblk_line_meta *lm = &pblk->lm;
699 void *ppa_list, *meta_list; 693 int bit;
700 struct bio *bio;
701 struct nvm_rq rqd;
702 dma_addr_t dma_ppa_list, dma_meta_list;
703 int min = pblk->min_write_pgs;
704 int left_ppas = lm->emeta_sec[0];
705 int id = line->id;
706 int rq_ppas, rq_len;
707 int cmd_op, bio_op;
708 int i, j;
709 int ret;
710 694
711 if (dir == PBLK_WRITE) { 695 /* This usually only happens on bad lines */
712 bio_op = REQ_OP_WRITE; 696 bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
713 cmd_op = NVM_OP_PWRITE; 697 if (bit >= lm->blk_per_line)
714 } else if (dir == PBLK_READ) { 698 return -1;
715 bio_op = REQ_OP_READ;
716 cmd_op = NVM_OP_PREAD;
717 } else
718 return -EINVAL;
719 699
720 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL, 700 return bit * geo->ws_opt;
721 &dma_meta_list); 701}
722 if (!meta_list)
723 return -ENOMEM;
724 702
725 ppa_list = meta_list + pblk_dma_meta_size; 703int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line)
726 dma_ppa_list = dma_meta_list + pblk_dma_meta_size; 704{
705 struct nvm_tgt_dev *dev = pblk->dev;
706 struct pblk_line_meta *lm = &pblk->lm;
707 struct bio *bio;
708 struct nvm_rq rqd;
709 u64 paddr = pblk_line_smeta_start(pblk, line);
710 int i, ret;
727 711
728next_rq:
729 memset(&rqd, 0, sizeof(struct nvm_rq)); 712 memset(&rqd, 0, sizeof(struct nvm_rq));
730 713
731 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0); 714 ret = pblk_alloc_rqd_meta(pblk, &rqd);
732 rq_len = rq_ppas * geo->csecs; 715 if (ret)
716 return ret;
733 717
734 bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len, 718 bio = bio_map_kern(dev->q, line->smeta, lm->smeta_len, GFP_KERNEL);
735 l_mg->emeta_alloc_type, GFP_KERNEL);
736 if (IS_ERR(bio)) { 719 if (IS_ERR(bio)) {
737 ret = PTR_ERR(bio); 720 ret = PTR_ERR(bio);
738 goto free_rqd_dma; 721 goto clear_rqd;
739 } 722 }
740 723
741 bio->bi_iter.bi_sector = 0; /* internal bio */ 724 bio->bi_iter.bi_sector = 0; /* internal bio */
742 bio_set_op_attrs(bio, bio_op, 0); 725 bio_set_op_attrs(bio, REQ_OP_READ, 0);
743 726
744 rqd.bio = bio; 727 rqd.bio = bio;
745 rqd.meta_list = meta_list; 728 rqd.opcode = NVM_OP_PREAD;
746 rqd.ppa_list = ppa_list; 729 rqd.nr_ppas = lm->smeta_sec;
747 rqd.dma_meta_list = dma_meta_list; 730 rqd.is_seq = 1;
748 rqd.dma_ppa_list = dma_ppa_list;
749 rqd.opcode = cmd_op;
750 rqd.nr_ppas = rq_ppas;
751
752 if (dir == PBLK_WRITE) {
753 struct pblk_sec_meta *meta_list = rqd.meta_list;
754
755 rqd.is_seq = 1;
756 for (i = 0; i < rqd.nr_ppas; ) {
757 spin_lock(&line->lock);
758 paddr = __pblk_alloc_page(pblk, line, min);
759 spin_unlock(&line->lock);
760 for (j = 0; j < min; j++, i++, paddr++) {
761 meta_list[i].lba = cpu_to_le64(ADDR_EMPTY);
762 rqd.ppa_list[i] =
763 addr_to_gen_ppa(pblk, paddr, id);
764 }
765 }
766 } else {
767 for (i = 0; i < rqd.nr_ppas; ) {
768 struct ppa_addr ppa = addr_to_gen_ppa(pblk, paddr, id);
769 int pos = pblk_ppa_to_pos(geo, ppa);
770
771 if (pblk_io_aligned(pblk, rq_ppas))
772 rqd.is_seq = 1;
773
774 while (test_bit(pos, line->blk_bitmap)) {
775 paddr += min;
776 if (pblk_boundary_paddr_checks(pblk, paddr)) {
777 pblk_err(pblk, "corrupt emeta line:%d\n",
778 line->id);
779 bio_put(bio);
780 ret = -EINTR;
781 goto free_rqd_dma;
782 }
783
784 ppa = addr_to_gen_ppa(pblk, paddr, id);
785 pos = pblk_ppa_to_pos(geo, ppa);
786 }
787
788 if (pblk_boundary_paddr_checks(pblk, paddr + min)) {
789 pblk_err(pblk, "corrupt emeta line:%d\n",
790 line->id);
791 bio_put(bio);
792 ret = -EINTR;
793 goto free_rqd_dma;
794 }
795 731
796 for (j = 0; j < min; j++, i++, paddr++) 732 for (i = 0; i < lm->smeta_sec; i++, paddr++)
797 rqd.ppa_list[i] = 733 rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
798 addr_to_gen_ppa(pblk, paddr, line->id);
799 }
800 }
801 734
802 ret = pblk_submit_io_sync(pblk, &rqd); 735 ret = pblk_submit_io_sync(pblk, &rqd);
803 if (ret) { 736 if (ret) {
804 pblk_err(pblk, "emeta I/O submission failed: %d\n", ret); 737 pblk_err(pblk, "smeta I/O submission failed: %d\n", ret);
805 bio_put(bio); 738 bio_put(bio);
806 goto free_rqd_dma; 739 goto clear_rqd;
807 } 740 }
808 741
809 atomic_dec(&pblk->inflight_io); 742 atomic_dec(&pblk->inflight_io);
810 743
811 if (rqd.error) { 744 if (rqd.error)
812 if (dir == PBLK_WRITE) 745 pblk_log_read_err(pblk, &rqd);
813 pblk_log_write_err(pblk, &rqd);
814 else
815 pblk_log_read_err(pblk, &rqd);
816 }
817 746
818 emeta_buf += rq_len; 747clear_rqd:
819 left_ppas -= rq_ppas; 748 pblk_free_rqd_meta(pblk, &rqd);
820 if (left_ppas)
821 goto next_rq;
822free_rqd_dma:
823 nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
824 return ret; 749 return ret;
825} 750}
826 751
827u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line) 752static int pblk_line_smeta_write(struct pblk *pblk, struct pblk_line *line,
828{ 753 u64 paddr)
829 struct nvm_tgt_dev *dev = pblk->dev;
830 struct nvm_geo *geo = &dev->geo;
831 struct pblk_line_meta *lm = &pblk->lm;
832 int bit;
833
834 /* This usually only happens on bad lines */
835 bit = find_first_zero_bit(line->blk_bitmap, lm->blk_per_line);
836 if (bit >= lm->blk_per_line)
837 return -1;
838
839 return bit * geo->ws_opt;
840}
841
842static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
843 u64 paddr, int dir)
844{ 754{
845 struct nvm_tgt_dev *dev = pblk->dev; 755 struct nvm_tgt_dev *dev = pblk->dev;
846 struct pblk_line_meta *lm = &pblk->lm; 756 struct pblk_line_meta *lm = &pblk->lm;
847 struct bio *bio; 757 struct bio *bio;
848 struct nvm_rq rqd; 758 struct nvm_rq rqd;
849 __le64 *lba_list = NULL; 759 __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf);
760 __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
850 int i, ret; 761 int i, ret;
851 int cmd_op, bio_op;
852
853 if (dir == PBLK_WRITE) {
854 bio_op = REQ_OP_WRITE;
855 cmd_op = NVM_OP_PWRITE;
856 lba_list = emeta_to_lbas(pblk, line->emeta->buf);
857 } else if (dir == PBLK_READ_RECOV || dir == PBLK_READ) {
858 bio_op = REQ_OP_READ;
859 cmd_op = NVM_OP_PREAD;
860 } else
861 return -EINVAL;
862 762
863 memset(&rqd, 0, sizeof(struct nvm_rq)); 763 memset(&rqd, 0, sizeof(struct nvm_rq));
864 764
@@ -873,30 +773,20 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
873 } 773 }
874 774
875 bio->bi_iter.bi_sector = 0; /* internal bio */ 775 bio->bi_iter.bi_sector = 0; /* internal bio */
876 bio_set_op_attrs(bio, bio_op, 0); 776 bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
877 777
878 rqd.bio = bio; 778 rqd.bio = bio;
879 rqd.opcode = cmd_op; 779 rqd.opcode = NVM_OP_PWRITE;
880 rqd.is_seq = 1;
881 rqd.nr_ppas = lm->smeta_sec; 780 rqd.nr_ppas = lm->smeta_sec;
781 rqd.is_seq = 1;
882 782
883 for (i = 0; i < lm->smeta_sec; i++, paddr++) { 783 for (i = 0; i < lm->smeta_sec; i++, paddr++) {
884 struct pblk_sec_meta *meta_list = rqd.meta_list; 784 struct pblk_sec_meta *meta_list = rqd.meta_list;
885 785
886 rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id); 786 rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line->id);
887 787 meta_list[i].lba = lba_list[paddr] = addr_empty;
888 if (dir == PBLK_WRITE) {
889 __le64 addr_empty = cpu_to_le64(ADDR_EMPTY);
890
891 meta_list[i].lba = lba_list[paddr] = addr_empty;
892 }
893 } 788 }
894 789
895 /*
896 * This I/O is sent by the write thread when a line is replace. Since
897 * the write thread is the only one sending write and erase commands,
898 * there is no need to take the LUN semaphore.
899 */
900 ret = pblk_submit_io_sync(pblk, &rqd); 790 ret = pblk_submit_io_sync(pblk, &rqd);
901 if (ret) { 791 if (ret) {
902 pblk_err(pblk, "smeta I/O submission failed: %d\n", ret); 792 pblk_err(pblk, "smeta I/O submission failed: %d\n", ret);
@@ -907,11 +797,8 @@ static int pblk_line_submit_smeta_io(struct pblk *pblk, struct pblk_line *line,
907 atomic_dec(&pblk->inflight_io); 797 atomic_dec(&pblk->inflight_io);
908 798
909 if (rqd.error) { 799 if (rqd.error) {
910 if (dir == PBLK_WRITE) { 800 pblk_log_write_err(pblk, &rqd);
911 pblk_log_write_err(pblk, &rqd); 801 ret = -EIO;
912 ret = 1;
913 } else if (dir == PBLK_READ)
914 pblk_log_read_err(pblk, &rqd);
915 } 802 }
916 803
917clear_rqd: 804clear_rqd:
@@ -919,18 +806,106 @@ clear_rqd:
919 return ret; 806 return ret;
920} 807}
921 808
922int pblk_line_read_smeta(struct pblk *pblk, struct pblk_line *line) 809int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line,
810 void *emeta_buf)
923{ 811{
924 u64 bpaddr = pblk_line_smeta_start(pblk, line); 812 struct nvm_tgt_dev *dev = pblk->dev;
813 struct nvm_geo *geo = &dev->geo;
814 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
815 struct pblk_line_meta *lm = &pblk->lm;
816 void *ppa_list, *meta_list;
817 struct bio *bio;
818 struct nvm_rq rqd;
819 u64 paddr = line->emeta_ssec;
820 dma_addr_t dma_ppa_list, dma_meta_list;
821 int min = pblk->min_write_pgs;
822 int left_ppas = lm->emeta_sec[0];
823 int line_id = line->id;
824 int rq_ppas, rq_len;
825 int i, j;
826 int ret;
925 827
926 return pblk_line_submit_smeta_io(pblk, line, bpaddr, PBLK_READ_RECOV); 828 meta_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
927} 829 &dma_meta_list);
830 if (!meta_list)
831 return -ENOMEM;
928 832
929int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line, 833 ppa_list = meta_list + pblk_dma_meta_size;
930 void *emeta_buf) 834 dma_ppa_list = dma_meta_list + pblk_dma_meta_size;
931{ 835
932 return pblk_line_submit_emeta_io(pblk, line, emeta_buf, 836next_rq:
933 line->emeta_ssec, PBLK_READ); 837 memset(&rqd, 0, sizeof(struct nvm_rq));
838
839 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0);
840 rq_len = rq_ppas * geo->csecs;
841
842 bio = pblk_bio_map_addr(pblk, emeta_buf, rq_ppas, rq_len,
843 l_mg->emeta_alloc_type, GFP_KERNEL);
844 if (IS_ERR(bio)) {
845 ret = PTR_ERR(bio);
846 goto free_rqd_dma;
847 }
848
849 bio->bi_iter.bi_sector = 0; /* internal bio */
850 bio_set_op_attrs(bio, REQ_OP_READ, 0);
851
852 rqd.bio = bio;
853 rqd.meta_list = meta_list;
854 rqd.ppa_list = ppa_list;
855 rqd.dma_meta_list = dma_meta_list;
856 rqd.dma_ppa_list = dma_ppa_list;
857 rqd.opcode = NVM_OP_PREAD;
858 rqd.nr_ppas = rq_ppas;
859
860 for (i = 0; i < rqd.nr_ppas; ) {
861 struct ppa_addr ppa = addr_to_gen_ppa(pblk, paddr, line_id);
862 int pos = pblk_ppa_to_pos(geo, ppa);
863
864 if (pblk_io_aligned(pblk, rq_ppas))
865 rqd.is_seq = 1;
866
867 while (test_bit(pos, line->blk_bitmap)) {
868 paddr += min;
869 if (pblk_boundary_paddr_checks(pblk, paddr)) {
870 bio_put(bio);
871 ret = -EINTR;
872 goto free_rqd_dma;
873 }
874
875 ppa = addr_to_gen_ppa(pblk, paddr, line_id);
876 pos = pblk_ppa_to_pos(geo, ppa);
877 }
878
879 if (pblk_boundary_paddr_checks(pblk, paddr + min)) {
880 bio_put(bio);
881 ret = -EINTR;
882 goto free_rqd_dma;
883 }
884
885 for (j = 0; j < min; j++, i++, paddr++)
886 rqd.ppa_list[i] = addr_to_gen_ppa(pblk, paddr, line_id);
887 }
888
889 ret = pblk_submit_io_sync(pblk, &rqd);
890 if (ret) {
891 pblk_err(pblk, "emeta I/O submission failed: %d\n", ret);
892 bio_put(bio);
893 goto free_rqd_dma;
894 }
895
896 atomic_dec(&pblk->inflight_io);
897
898 if (rqd.error)
899 pblk_log_read_err(pblk, &rqd);
900
901 emeta_buf += rq_len;
902 left_ppas -= rq_ppas;
903 if (left_ppas)
904 goto next_rq;
905
906free_rqd_dma:
907 nvm_dev_dma_free(dev->parent, rqd.meta_list, rqd.dma_meta_list);
908 return ret;
934} 909}
935 910
936static void pblk_setup_e_rq(struct pblk *pblk, struct nvm_rq *rqd, 911static void pblk_setup_e_rq(struct pblk *pblk, struct nvm_rq *rqd,
@@ -1169,7 +1144,7 @@ static int pblk_line_init_bb(struct pblk *pblk, struct pblk_line *line,
1169 line->smeta_ssec = off; 1144 line->smeta_ssec = off;
1170 line->cur_sec = off + lm->smeta_sec; 1145 line->cur_sec = off + lm->smeta_sec;
1171 1146
1172 if (init && pblk_line_submit_smeta_io(pblk, line, off, PBLK_WRITE)) { 1147 if (init && pblk_line_smeta_write(pblk, line, off)) {
1173 pblk_debug(pblk, "line smeta I/O failed. Retry\n"); 1148 pblk_debug(pblk, "line smeta I/O failed. Retry\n");
1174 return 0; 1149 return 0;
1175 } 1150 }
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index b841d84c4342..e05d06bd5b83 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -148,7 +148,7 @@ static __le64 *get_lba_list_from_emeta(struct pblk *pblk,
148 if (!emeta_buf) 148 if (!emeta_buf)
149 return NULL; 149 return NULL;
150 150
151 ret = pblk_line_read_emeta(pblk, line, emeta_buf); 151 ret = pblk_line_emeta_read(pblk, line, emeta_buf);
152 if (ret) { 152 if (ret) {
153 pblk_err(pblk, "line %d read emeta failed (%d)\n", 153 pblk_err(pblk, "line %d read emeta failed (%d)\n",
154 line->id, ret); 154 line->id, ret);
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index 218292979953..6c57eb00a7f1 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -836,7 +836,7 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
836 continue; 836 continue;
837 837
838 /* Lines that cannot be read are assumed as not written here */ 838 /* Lines that cannot be read are assumed as not written here */
839 if (pblk_line_read_smeta(pblk, line)) 839 if (pblk_line_smeta_read(pblk, line))
840 continue; 840 continue;
841 841
842 crc = pblk_calc_smeta_crc(pblk, smeta_buf); 842 crc = pblk_calc_smeta_crc(pblk, smeta_buf);
@@ -906,7 +906,7 @@ struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
906 line->emeta = emeta; 906 line->emeta = emeta;
907 memset(line->emeta->buf, 0, lm->emeta_len[0]); 907 memset(line->emeta->buf, 0, lm->emeta_len[0]);
908 908
909 if (pblk_line_read_emeta(pblk, line, line->emeta->buf)) { 909 if (pblk_line_emeta_read(pblk, line, line->emeta->buf)) {
910 pblk_recov_l2p_from_oob(pblk, line); 910 pblk_recov_l2p_from_oob(pblk, line);
911 goto next; 911 goto next;
912 } 912 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index b06ab0edab69..02e2c02b0cf4 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -819,8 +819,8 @@ void pblk_gen_run_ws(struct pblk *pblk, struct pblk_line *line, void *priv,
819 void (*work)(struct work_struct *), gfp_t gfp_mask, 819 void (*work)(struct work_struct *), gfp_t gfp_mask,
820 struct workqueue_struct *wq); 820 struct workqueue_struct *wq);
821u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line); 821u64 pblk_line_smeta_start(struct pblk *pblk, struct pblk_line *line);
822int pblk_line_read_smeta(struct pblk *pblk, struct pblk_line *line); 822int pblk_line_smeta_read(struct pblk *pblk, struct pblk_line *line);
823int pblk_line_read_emeta(struct pblk *pblk, struct pblk_line *line, 823int pblk_line_emeta_read(struct pblk *pblk, struct pblk_line *line,
824 void *emeta_buf); 824 void *emeta_buf);
825int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr erase_ppa); 825int pblk_blk_erase_async(struct pblk *pblk, struct ppa_addr erase_ppa);
826void pblk_line_put(struct kref *ref); 826void pblk_line_put(struct kref *ref);