Lines Matching refs:pblk
15 * pblk-recovery.c - pblk's recovery path
21 #include "pblk.h"
22 #include "pblk-trace.h"
24 int pblk_recov_check_emeta(struct pblk *pblk, struct line_emeta *emeta_buf)
28 crc = pblk_calc_emeta_crc(pblk, emeta_buf);
38 static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line)
40 struct nvm_tgt_dev *dev = pblk->dev;
42 struct pblk_line_meta *lm = &pblk->lm;
50 lba_list = emeta_to_lbas(pblk, emeta_buf);
54 data_start = pblk_line_smeta_start(pblk, line) + lm->smeta_sec;
62 ppa = addr_to_gen_ppa(pblk, i, line->id);
72 WARN_ONCE(1, "pblk: rec. double invalidate:\n");
80 pblk_update_map(pblk, le64_to_cpu(lba_list[i]), ppa);
85 pblk_err(pblk, "line %d - inconsistent lba list(%llu/%llu)\n",
93 static void pblk_update_line_wp(struct pblk *pblk, struct pblk_line *line,
96 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
99 for (i = 0; i < written_secs; i += pblk->min_write_pgs)
100 __pblk_alloc_page(pblk, line, pblk->min_write_pgs);
116 static u64 pblk_sec_in_open_line(struct pblk *pblk, struct pblk_line *line)
118 struct pblk_line_meta *lm = &pblk->lm;
135 pblk_err(pblk, "recovery line %d is bad\n", line->id);
137 pblk_update_line_wp(pblk, line, written_secs - lm->smeta_sec);
162 struct pblk *pblk = pad_rq->pblk;
164 pblk_up_chunk(pblk, ppa_list[0]);
166 pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
168 atomic_dec(&pblk->inflight_io);
173 static int pblk_recov_pad_line(struct pblk *pblk, struct pblk_line *line,
176 struct nvm_tgt_dev *dev = pblk->dev;
183 __le64 *lba_list = emeta_to_lbas(pblk, line->emeta->buf);
197 data = vzalloc(array_size(pblk->max_write_pgs, geo->csecs));
203 pad_rq->pblk = pblk;
208 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0, false);
209 if (rq_ppas < pblk->min_write_pgs) {
210 pblk_err(pblk, "corrupted pad line %d\n", line->id);
214 rqd = pblk_alloc_rqd(pblk, PBLK_WRITE_INT);
216 ret = pblk_alloc_rqd_meta(pblk, rqd);
218 pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
236 w_ptr = pblk_alloc_page(pblk, line, pblk->min_write_pgs);
237 ppa = addr_to_gen_ppa(pblk, w_ptr, line->id);
241 w_ptr += pblk->min_write_pgs;
242 ppa = addr_to_gen_ppa(pblk, w_ptr, line->id);
246 for (j = 0; j < pblk->min_write_pgs; j++, i++, w_ptr++) {
251 dev_ppa = addr_to_gen_ppa(pblk, w_ptr, line->id);
253 pblk_map_invalidate(pblk, dev_ppa);
255 meta = pblk_get_meta(pblk, meta_list, i);
262 pblk_down_chunk(pblk, ppa_list[0]);
264 ret = pblk_submit_io(pblk, rqd, data);
266 pblk_err(pblk, "I/O submission failed: %d\n", ret);
267 pblk_up_chunk(pblk, ppa_list[0]);
269 pblk_free_rqd(pblk, rqd, PBLK_WRITE_INT);
283 pblk_err(pblk, "corrupted padded line: %d\n", line->id);
291 static int pblk_pad_distance(struct pblk *pblk, struct pblk_line *line)
293 struct nvm_tgt_dev *dev = pblk->dev;
301 static struct nvm_chk_meta *pblk_get_stripe_chunk(struct pblk *pblk,
305 struct nvm_tgt_dev *dev = pblk->dev;
311 rlun = &pblk->luns[index];
318 static int pblk_line_wps_are_unbalanced(struct pblk *pblk,
321 struct pblk_line_meta *lm = &pblk->lm;
335 chunk = pblk_get_stripe_chunk(pblk, line, i);
337 if (max_wp > pblk->max_write_pgs)
338 min_wp = max_wp - pblk->max_write_pgs;
344 chunk = pblk_get_stripe_chunk(pblk, line, i);
354 static int pblk_recov_scan_oob(struct pblk *pblk, struct pblk_line *line,
357 struct nvm_tgt_dev *dev = pblk->dev;
358 struct pblk_line_meta *lm = &pblk->lm;
366 u64 paddr = pblk_line_smeta_start(pblk, line) + lm->smeta_sec;
371 u64 left_ppas = pblk_sec_in_open_line(pblk, line) - lm->smeta_sec;
373 if (pblk_line_wps_are_unbalanced(pblk, line))
374 pblk_warn(pblk, "recovering unbalanced line (%d)\n", line->id);
383 lba_list = emeta_to_lbas(pblk, line->emeta->buf);
388 rq_ppas = pblk_calc_secs(pblk, left_ppas, 0, false);
390 rq_ppas = pblk->min_write_pgs;
402 if (pblk_io_aligned(pblk, rq_ppas))
409 ppa = addr_to_gen_ppa(pblk, paddr, line->id);
413 paddr += pblk->min_write_pgs;
414 ppa = addr_to_gen_ppa(pblk, paddr, line->id);
418 for (j = 0; j < pblk->min_write_pgs; j++, i++)
420 addr_to_gen_ppa(pblk, paddr + j, line->id);
423 ret = pblk_submit_io_sync(pblk, rqd, data);
425 pblk_err(pblk, "I/O submission failed: %d\n", ret);
429 atomic_dec(&pblk->inflight_io);
436 pblk_log_read_err(pblk, rqd);
440 pad_distance = pblk_pad_distance(pblk, line);
441 ret = pblk_recov_pad_line(pblk, line, pad_distance);
450 pblk_get_packed_meta(pblk, rqd);
453 struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i);
458 if (lba == ADDR_EMPTY || lba >= pblk->capacity)
462 pblk_update_map(pblk, lba, ppa_list[i]);
477 static int pblk_recov_l2p_from_oob(struct pblk *pblk, struct pblk_line *line)
479 struct nvm_tgt_dev *dev = pblk->dev;
493 ppa_list = (void *)(meta_list) + pblk_dma_meta_size(pblk);
494 dma_ppa_list = dma_meta_list + pblk_dma_meta_size(pblk);
496 data = kcalloc(pblk->max_write_pgs, geo->csecs, GFP_KERNEL);
502 rqd = mempool_alloc(&pblk->r_rq_pool, GFP_KERNEL);
512 ret = pblk_recov_scan_oob(pblk, line, p);
514 pblk_err(pblk, "could not recover L2P form OOB\n");
519 pblk_line_recov_close(pblk, line);
522 mempool_free(rqd, &pblk->r_rq_pool);
543 static u64 pblk_line_emeta_start(struct pblk *pblk, struct pblk_line *line)
545 struct nvm_tgt_dev *dev = pblk->dev;
547 struct pblk_line_meta *lm = &pblk->lm;
558 ppa = addr_to_gen_ppa(pblk, emeta_start, line->id);
567 static int pblk_recov_check_line_version(struct pblk *pblk,
573 pblk_err(pblk, "line major version mismatch: %d, expected: %d\n",
580 pblk_info(pblk, "newer line minor version found: %d\n",
587 static void pblk_recov_wa_counters(struct pblk *pblk,
590 struct pblk_line_meta *lm = &pblk->lm;
600 atomic64_set(&pblk->user_wa, user);
601 atomic64_set(&pblk->pad_wa, pad);
602 atomic64_set(&pblk->gc_wa, gc);
604 pblk->user_rst_wa = user;
605 pblk->pad_rst_wa = pad;
606 pblk->gc_rst_wa = gc;
611 struct pblk *pblk)
614 struct pblk_line_meta *lm = &pblk->lm;
615 struct nvm_tgt_dev *dev = pblk->dev;
628 bppa = pblk->luns[smeta_blk].bppa;
639 static bool pblk_line_is_open(struct pblk *pblk, struct pblk_line *line)
641 struct pblk_line_meta *lm = &pblk->lm;
651 struct pblk_line *pblk_recov_l2p(struct pblk *pblk)
653 struct pblk_line_meta *lm = &pblk->lm;
654 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
680 line = &pblk->lines[i];
687 if (!pblk_line_was_written(line, pblk))
691 if (pblk_line_smeta_read(pblk, line))
694 crc = pblk_calc_smeta_crc(pblk, smeta_buf);
702 pblk_err(pblk, "found incompatible line version %u\n",
709 guid_copy(&pblk->instance_uuid,
714 if (!guid_equal(&pblk->instance_uuid,
716 pblk_debug(pblk, "ignore line %u due to uuid mismatch\n",
735 if (pblk_line_recov_alloc(pblk, line))
740 pblk_debug(pblk, "recovering data line %d, seq:%llu\n",
745 guid_gen(&pblk->instance_uuid);
759 line->emeta_ssec = pblk_line_emeta_start(pblk, line);
763 if (pblk_line_is_open(pblk, line)) {
764 pblk_recov_l2p_from_oob(pblk, line);
768 if (pblk_line_emeta_read(pblk, line, line->emeta->buf)) {
769 pblk_recov_l2p_from_oob(pblk, line);
773 if (pblk_recov_check_emeta(pblk, line->emeta->buf)) {
774 pblk_recov_l2p_from_oob(pblk, line);
778 if (pblk_recov_check_line_version(pblk, line->emeta->buf))
781 pblk_recov_wa_counters(pblk, line->emeta->buf);
783 if (pblk_recov_l2p_from_emeta(pblk, line))
784 pblk_recov_l2p_from_oob(pblk, line);
792 trace_pblk_line_state(pblk_disk_name(pblk), line->id,
794 move_list = pblk_line_gc_list(pblk, line);
813 trace_pblk_line_state(pblk_disk_name(pblk), line->id,
832 l_mg->data_next = pblk_line_get(pblk);
842 pblk_line_erase(pblk, l_mg->data_next);
846 pblk_err(pblk, "failed to recover all found lines %d/%d\n",
855 int pblk_recov_pad(struct pblk *pblk)
858 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
867 ret = pblk_recov_pad_line(pblk, line, left_msecs);
869 pblk_err(pblk, "tear down padding failed (%d)\n", ret);
873 pblk_line_close_meta(pblk, line);