diff options
author | Javier González <javier@javigon.com> | 2018-06-01 09:04:17 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-06-01 09:43:53 -0400 |
commit | 310df58229f69382c0c4c9e9003790b71b8a7a55 (patch) | |
tree | 3b073778d28dfb4d1a8ecdbf6ca8ff0b1dc5e39e /drivers/lightnvm | |
parent | 1d8b33e05cea69a1b0b7f2f2a7c102b6583a984f (diff) |
lightnvm: pblk: check read lba on gc path
Check that the lba stored in the LBA metadata is correct in the GC path
too. This requires a new helper function to check random reads in the
vector read.
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-read.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c index c844ffb6aead..f3cc61b87a4f 100644 --- a/drivers/lightnvm/pblk-read.c +++ b/drivers/lightnvm/pblk-read.c | |||
@@ -113,15 +113,14 @@ static int pblk_submit_read_io(struct pblk *pblk, struct nvm_rq *rqd) | |||
113 | return NVM_IO_OK; | 113 | return NVM_IO_OK; |
114 | } | 114 | } |
115 | 115 | ||
116 | static void pblk_read_check(struct pblk *pblk, struct nvm_rq *rqd, | 116 | static void pblk_read_check_seq(struct pblk *pblk, void *meta_list, |
117 | sector_t blba) | 117 | sector_t blba, int nr_lbas) |
118 | { | 118 | { |
119 | struct pblk_sec_meta *meta_list = rqd->meta_list; | 119 | struct pblk_sec_meta *meta_lba_list = meta_list; |
120 | int nr_lbas = rqd->nr_ppas; | ||
121 | int i; | 120 | int i; |
122 | 121 | ||
123 | for (i = 0; i < nr_lbas; i++) { | 122 | for (i = 0; i < nr_lbas; i++) { |
124 | u64 lba = le64_to_cpu(meta_list[i].lba); | 123 | u64 lba = le64_to_cpu(meta_lba_list[i].lba); |
125 | 124 | ||
126 | if (lba == ADDR_EMPTY) | 125 | if (lba == ADDR_EMPTY) |
127 | continue; | 126 | continue; |
@@ -130,6 +129,32 @@ static void pblk_read_check(struct pblk *pblk, struct nvm_rq *rqd, | |||
130 | } | 129 | } |
131 | } | 130 | } |
132 | 131 | ||
132 | /* | ||
133 | * There can be holes in the lba list. | ||
134 | */ | ||
135 | static void pblk_read_check_rand(struct pblk *pblk, void *meta_list, | ||
136 | u64 *lba_list, int nr_lbas) | ||
137 | { | ||
138 | struct pblk_sec_meta *meta_lba_list = meta_list; | ||
139 | int i, j; | ||
140 | |||
141 | for (i = 0, j = 0; i < nr_lbas; i++) { | ||
142 | u64 lba = lba_list[i]; | ||
143 | u64 meta_lba; | ||
144 | |||
145 | if (lba == ADDR_EMPTY) | ||
146 | continue; | ||
147 | |||
148 | meta_lba = le64_to_cpu(meta_lba_list[j++].lba); | ||
149 | |||
150 | if (lba != meta_lba) { | ||
151 | pr_err("pblk: corrupted read LBA (%llu/%llu)\n", | ||
152 | lba, meta_lba); | ||
153 | WARN_ON(1); | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
133 | static void pblk_read_put_rqd_kref(struct pblk *pblk, struct nvm_rq *rqd) | 158 | static void pblk_read_put_rqd_kref(struct pblk *pblk, struct nvm_rq *rqd) |
134 | { | 159 | { |
135 | struct ppa_addr *ppa_list; | 160 | struct ppa_addr *ppa_list; |
@@ -172,7 +197,7 @@ static void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd, | |||
172 | WARN_ONCE(bio->bi_status, "pblk: corrupted read error\n"); | 197 | WARN_ONCE(bio->bi_status, "pblk: corrupted read error\n"); |
173 | #endif | 198 | #endif |
174 | 199 | ||
175 | pblk_read_check(pblk, rqd, r_ctx->lba); | 200 | pblk_read_check_seq(pblk, rqd->meta_list, r_ctx->lba, rqd->nr_ppas); |
176 | 201 | ||
177 | bio_put(bio); | 202 | bio_put(bio); |
178 | if (r_ctx->private) | 203 | if (r_ctx->private) |
@@ -585,6 +610,8 @@ int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) | |||
585 | goto err_free_bio; | 610 | goto err_free_bio; |
586 | } | 611 | } |
587 | 612 | ||
613 | pblk_read_check_rand(pblk, rqd.meta_list, gc_rq->lba_list, rqd.nr_ppas); | ||
614 | |||
588 | atomic_dec(&pblk->inflight_io); | 615 | atomic_dec(&pblk->inflight_io); |
589 | 616 | ||
590 | if (rqd.error) { | 617 | if (rqd.error) { |