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 <[email protected]>
> ---
>  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

Reply via email to