in btt.c [1198:1294]
static int btt_read_pg(struct btt *btt, struct bio_integrity_payload *bip,
struct page *page, unsigned int off, sector_t sector,
unsigned int len)
{
int ret = 0;
int t_flag, e_flag;
struct arena_info *arena = NULL;
u32 lane = 0, premap, postmap;
while (len) {
u32 cur_len;
lane = nd_region_acquire_lane(btt->nd_region);
ret = lba_to_arena(btt, sector, &premap, &arena);
if (ret)
goto out_lane;
cur_len = min(btt->sector_size, len);
ret = btt_map_read(arena, premap, &postmap, &t_flag, &e_flag,
NVDIMM_IO_ATOMIC);
if (ret)
goto out_lane;
/*
* We loop to make sure that the post map LBA didn't change
* from under us between writing the RTT and doing the actual
* read.
*/
while (1) {
u32 new_map;
int new_t, new_e;
if (t_flag) {
zero_fill_data(page, off, cur_len);
goto out_lane;
}
if (e_flag) {
ret = -EIO;
goto out_lane;
}
arena->rtt[lane] = RTT_VALID | postmap;
/*
* Barrier to make sure this write is not reordered
* to do the verification map_read before the RTT store
*/
barrier();
ret = btt_map_read(arena, premap, &new_map, &new_t,
&new_e, NVDIMM_IO_ATOMIC);
if (ret)
goto out_rtt;
if ((postmap == new_map) && (t_flag == new_t) &&
(e_flag == new_e))
break;
postmap = new_map;
t_flag = new_t;
e_flag = new_e;
}
ret = btt_data_read(arena, page, off, postmap, cur_len);
if (ret) {
/* Media error - set the e_flag */
if (btt_map_write(arena, premap, postmap, 0, 1, NVDIMM_IO_ATOMIC))
dev_warn_ratelimited(to_dev(arena),
"Error persistently tracking bad blocks at %#x\n",
premap);
goto out_rtt;
}
if (bip) {
ret = btt_rw_integrity(btt, bip, arena, postmap, READ);
if (ret)
goto out_rtt;
}
arena->rtt[lane] = RTT_INVALID;
nd_region_release_lane(btt->nd_region, lane);
len -= cur_len;
off += cur_len;
sector += btt->sector_size >> SECTOR_SHIFT;
}
return 0;
out_rtt:
arena->rtt[lane] = RTT_INVALID;
out_lane:
nd_region_release_lane(btt->nd_region, lane);
return ret;
}