On 02/17/2016 12:00 PM, Javier González wrote: > In rrpc, some calculations assume a certain configuration (e.g., 1 LUN, > 1 sector per page). The reason behind this was that we have used a simple > configuration in QEMU to test core features generally in LightNVM, and > concretely in rrpc. This patch relaxes these assumptions and generalizes > calculations in order to support real hardware. Note that more complex > configurations in QEMU, that allow to simulate this hardware, are also > pushed into the qemu-nvme repository implementing LightNVM support, > available under the Open-Channel SSD project in github [1]. > > [1] https://github.com/OpenChannelSSD/qemu-nvme > > Signed-off-by: Javier González <javier@xxxxxxxxxxxx> > --- > drivers/lightnvm/rrpc.c | 45 ++++++++++++++++++++++++++++----------------- > drivers/lightnvm/rrpc.h | 9 +++++++++ > 2 files changed, 37 insertions(+), 17 deletions(-) > > diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c > index 775bf6c2..f366c78 100644 > --- a/drivers/lightnvm/rrpc.c > +++ b/drivers/lightnvm/rrpc.c > @@ -38,7 +38,7 @@ static void rrpc_page_invalidate(struct rrpc *rrpc, struct rrpc_addr *a) > > spin_lock(&rblk->lock); > > - div_u64_rem(a->addr, rrpc->dev->pgs_per_blk, &pg_offset); > + div_u64_rem(a->addr, rrpc->dev->sec_per_blk, &pg_offset); > WARN_ON(test_and_set_bit(pg_offset, rblk->invalid_pages)); > rblk->nr_invalid_pages++; > > @@ -113,14 +113,24 @@ static void rrpc_discard(struct rrpc *rrpc, struct bio *bio) > > static int block_is_full(struct rrpc *rrpc, struct rrpc_block *rblk) > { > - return (rblk->next_page == rrpc->dev->pgs_per_blk); > + return (rblk->next_page == rrpc->dev->sec_per_blk); > } > > +/* Calculate relative addr for the given block, considering instantiated LUNs */ > +static u64 block_to_rel_addr(struct rrpc *rrpc, struct rrpc_block *rblk) > +{ > + struct nvm_block *blk = rblk->parent; > + int lun_blk = blk->id % (rrpc->dev->blks_per_lun * rrpc->nr_luns); > + > + return lun_blk * rrpc->dev->sec_per_blk; > +} > + > +/* Calculate global addr for the given block */ > static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk) > { > struct nvm_block *blk = rblk->parent; > > - return blk->id * rrpc->dev->pgs_per_blk; > + return blk->id * rrpc->dev->sec_per_blk; > } > > static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev, > @@ -136,7 +146,7 @@ static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev, > l.g.sec = secs; > > sector_div(ppa, dev->sec_per_pg); > - div_u64_rem(ppa, dev->sec_per_blk, &pgs); > + div_u64_rem(ppa, dev->pgs_per_blk, &pgs); > l.g.pg = pgs; > > sector_div(ppa, dev->pgs_per_blk); > @@ -191,12 +201,12 @@ static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun, > return NULL; > } > > - rblk = &rlun->blocks[blk->id]; > + rblk = rrpc_get_rblk(rlun, blk->id); > list_add_tail(&rblk->list, &rlun->open_list); > spin_unlock(&lun->lock); > > blk->priv = rblk; > - bitmap_zero(rblk->invalid_pages, rrpc->dev->pgs_per_blk); > + bitmap_zero(rblk->invalid_pages, rrpc->dev->sec_per_blk); > rblk->next_page = 0; > rblk->nr_invalid_pages = 0; > atomic_set(&rblk->data_cmnt_size, 0); > @@ -286,11 +296,11 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk) > struct bio *bio; > struct page *page; > int slot; > - int nr_pgs_per_blk = rrpc->dev->pgs_per_blk; > + int nr_sec_per_blk = rrpc->dev->sec_per_blk; > u64 phys_addr; > DECLARE_COMPLETION_ONSTACK(wait); > > - if (bitmap_full(rblk->invalid_pages, nr_pgs_per_blk)) > + if (bitmap_full(rblk->invalid_pages, nr_sec_per_blk)) > return 0; > > bio = bio_alloc(GFP_NOIO, 1); > @@ -306,10 +316,10 @@ static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk) > } > > while ((slot = find_first_zero_bit(rblk->invalid_pages, > - nr_pgs_per_blk)) < nr_pgs_per_blk) { > + nr_sec_per_blk)) < nr_sec_per_blk) { > > /* Lock laddr */ > - phys_addr = (rblk->parent->id * nr_pgs_per_blk) + slot; > + phys_addr = rblk->parent->id * nr_sec_per_blk + slot; > > try: > spin_lock(&rrpc->rev_lock); > @@ -381,7 +391,7 @@ finished: > mempool_free(page, rrpc->page_pool); > bio_put(bio); > > - if (!bitmap_full(rblk->invalid_pages, nr_pgs_per_blk)) { > + if (!bitmap_full(rblk->invalid_pages, nr_sec_per_blk)) { > pr_err("nvm: failed to garbage collect block\n"); > return -EIO; > } > @@ -677,7 +687,7 @@ static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd, > lun = rblk->parent->lun; > > cmnt_size = atomic_inc_return(&rblk->data_cmnt_size); > - if (unlikely(cmnt_size == rrpc->dev->pgs_per_blk)) > + if (unlikely(cmnt_size == rrpc->dev->sec_per_blk)) > rrpc_run_gc(rrpc, rblk); > } > } > @@ -1030,7 +1040,7 @@ static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private) > continue; > > addr[i].addr = pba; > - raddr[pba].addr = slba + i; > + raddr[pba % rrpc->nr_sects].addr = slba + i; > } > > return 0; > @@ -1137,7 +1147,7 @@ static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end) > struct rrpc_lun *rlun; > int i, j; > > - if (dev->pgs_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) { > + if (dev->sec_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) { > pr_err("rrpc: number of pages per block too high."); > return -EINVAL; > } > @@ -1238,10 +1248,11 @@ static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk) > struct nvm_dev *dev = rrpc->dev; > int offset; > struct rrpc_addr *laddr; > - u64 paddr, pladdr; > + u64 bpaddr, paddr, pladdr; > > - for (offset = 0; offset < dev->pgs_per_blk; offset++) { > - paddr = block_to_addr(rrpc, rblk) + offset; > + bpaddr = block_to_rel_addr(rrpc, rblk); > + for (offset = 0; offset < dev->sec_per_blk; offset++) { > + paddr = bpaddr + offset; > > pladdr = rrpc->rev_trans_map[paddr].addr; > if (pladdr == ADDR_EMPTY) > diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h > index 3989d65..855f4a5 100644 > --- a/drivers/lightnvm/rrpc.h > +++ b/drivers/lightnvm/rrpc.h > @@ -156,6 +156,15 @@ struct rrpc_rev_addr { > u64 addr; > }; > > +static inline struct rrpc_block *rrpc_get_rblk(struct rrpc_lun *rlun, > + int blk_id) > +{ > + struct rrpc *rrpc = rlun->rrpc; > + int lun_blk = blk_id % rrpc->dev->blks_per_lun; > + > + return &rlun->blocks[lun_blk]; > +} > + > static inline sector_t rrpc_get_laddr(struct bio *bio) > { > return bio->bi_iter.bi_sector / NR_PHY_IN_LOG; > Thanks Javier, applied. -Matias -- To unsubscribe from this list: send the line "unsubscribe linux-block" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html