static int pblk_recov_l2p_from_emeta(struct pblk *pblk, struct pblk_line *line) { struct nvm_tgt_dev *dev = pblk->dev; struct nvm_geo *geo = &dev->geo; struct pblk_line_meta *lm = &pblk->lm; struct pblk_emeta *emeta = line->emeta; struct line_emeta *emeta_buf = emeta->buf; __le64 *lba_list; u64 data_start, data_end; u64 nr_valid_lbas, nr_lbas = 0; u64 i; lba_list = emeta_to_lbas(pblk, emeta_buf); if (!lba_list) return 1; data_start = pblk_line_smeta_start(pblk, line) + lm->smeta_sec; data_end = line->emeta_ssec; nr_valid_lbas = le64_to_cpu(emeta_buf->nr_valid_lbas); for (i = data_start; i < data_end; i++) { struct ppa_addr ppa; int pos; ppa = addr_to_gen_ppa(pblk, i, line->id); pos = pblk_ppa_to_pos(geo, ppa); /* Do not update bad blocks */ if (test_bit(pos, line->blk_bitmap)) continue; if (le64_to_cpu(lba_list[i]) == ADDR_EMPTY) { spin_lock(&line->lock); if (test_and_set_bit(i, line->invalid_bitmap)) WARN_ONCE(1, "pblk: rec. double invalidate:\n"); else le32_add_cpu(line->vsc, -1); spin_unlock(&line->lock); continue; } pblk_update_map(pblk, le64_to_cpu(lba_list[i]), ppa); nr_lbas++; } if (nr_valid_lbas != nr_lbas) pblk_err(pblk, "line %d - inconsistent lba list(%llu/%llu)\n", line->id, nr_valid_lbas, nr_lbas); line->left_msecs = 0; return 0; }
__le64 *pblk_recov_get_lba_list(struct pblk *pblk, struct line_emeta *emeta_buf) { u32 crc; crc = pblk_calc_emeta_crc(pblk, emeta_buf); if (le32_to_cpu(emeta_buf->crc) != crc) return NULL; if (le32_to_cpu(emeta_buf->header.identifier) != PBLK_MAGIC) return NULL; return emeta_to_lbas(pblk, emeta_buf); }