On 02/04/2016 12:34 PM, Wenwei Tao wrote:
> Add a bitmap of luns to indicate the status
> of luns: inuse/available. When create targets
> do the necessary check to avoid allocating luns
> that are already allocated.
> 
> Signed-off-by: Wenwei Tao <[email protected]>
> ---
>  drivers/lightnvm/core.c   |  5 ++++
>  drivers/lightnvm/gennvm.c | 18 +++++++++++++++
>  drivers/lightnvm/rrpc.c   | 59 
> +++++++++++++++++++++++++++++++++++------------
>  include/linux/lightnvm.h  |  5 ++++
>  4 files changed, 72 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index 93c035b..11b8e2d 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -464,6 +464,10 @@ static int nvm_core_init(struct nvm_dev *dev)
>       dev->nr_luns = dev->luns_per_chnl * dev->nr_chnls;
>  
>       dev->total_secs = dev->nr_luns * dev->sec_per_lun;
> +     dev->lun_map = kcalloc(BITS_TO_LONGS(dev->nr_luns),
> +             sizeof(unsigned long), GFP_KERNEL);
> +     if (!dev->lun_map)
> +             return -ENOMEM;
>       INIT_LIST_HEAD(&dev->online_targets);
>       mutex_init(&dev->mlock);
>       spin_lock_init(&dev->lock);
> @@ -606,6 +610,7 @@ void nvm_unregister(char *disk_name)
>       up_write(&nvm_lock);
>  
>       nvm_exit(dev);
> +     kfree(dev->lun_map);
>       kfree(dev);
>  }
>  EXPORT_SYMBOL(nvm_unregister);
> diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c
> index fba3fbd..adc10c2 100644
> --- a/drivers/lightnvm/gennvm.c
> +++ b/drivers/lightnvm/gennvm.c
> @@ -190,6 +190,9 @@ static int gennvm_block_map(u64 slba, u32 nlb, __le64 
> *entries, void *private)
>               lun_id = div_u64(pba, dev->sec_per_lun);
>               lun = &gn->luns[lun_id];
>  
> +             if (!test_bit(lun_id, dev->lun_map))
> +                     __set_bit(lun_id, dev->lun_map);
> +
>               /* Calculate block offset into lun */
>               pba = pba - (dev->sec_per_lun * lun_id);
>               blk = &lun->vlun.blocks[div_u64(pba, dev->sec_per_blk)];
> @@ -480,10 +483,23 @@ static int gennvm_erase_blk(struct nvm_dev *dev, struct 
> nvm_block *blk,
>       return nvm_erase_ppa(dev, &addr, 1);
>  }
>  
> +static int gennvm_reserve_lun(struct nvm_dev *dev, int lunid)
> +{
> +     return test_and_set_bit(lunid, dev->lun_map);
> +}
> +
> +static void gennvm_release_lun(struct nvm_dev *dev, int lunid)
> +{
> +     WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
> +}
> +
>  static struct nvm_lun *gennvm_get_lun(struct nvm_dev *dev, int lunid)
>  {
>       struct gen_nvm *gn = dev->mp;
>  
> +     if (unlikely(lunid >= dev->nr_luns))
> +             return NULL;
> +
>       return &gn->luns[lunid].vlun;
>  }
>  
> @@ -525,6 +541,8 @@ static struct nvmm_type gennvm = {
>       .erase_blk              = gennvm_erase_blk,
>  
>       .get_lun                = gennvm_get_lun,
> +     .reserve_lun            = gennvm_reserve_lun,
> +     .release_lun            = gennvm_release_lun,
>       .lun_info_print         = gennvm_lun_info_print,
>  
>       .get_area               = gennvm_get_area,
> diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c
> index 6ce5f73..2bd5789 100644
> --- a/drivers/lightnvm/rrpc.c
> +++ b/drivers/lightnvm/rrpc.c
> @@ -1128,6 +1128,22 @@ static void rrpc_core_free(struct rrpc *rrpc)
>  
>  static void rrpc_luns_free(struct rrpc *rrpc)
>  {
> +     struct nvm_dev *dev = rrpc->dev;
> +     struct nvm_lun *lun;
> +     struct rrpc_lun *rlun;
> +     int i;
> +
> +     if (!rrpc->luns)
> +             return;
> +
> +     for (i = 0; i < rrpc->nr_luns; i++) {
> +             rlun = &rrpc->luns[i];
> +             lun = rlun->parent;
> +             if (!lun)
> +                     break;
> +             dev->mt->release_lun(dev, lun->id);
> +             vfree(rlun->blocks);
> +     }
>       kfree(rrpc->luns);
>  }
>  
> @@ -1135,7 +1151,7 @@ static int rrpc_luns_init(struct rrpc *rrpc, int 
> lun_begin, int lun_end)
>  {
>       struct nvm_dev *dev = rrpc->dev;
>       struct rrpc_lun *rlun;
> -     int i, j;
> +     int i, j, ret = -EINVAL;
>  
>       if (dev->pgs_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
>               pr_err("rrpc: number of pages per block too high.");
> @@ -1151,25 +1167,26 @@ static int rrpc_luns_init(struct rrpc *rrpc, int 
> lun_begin, int lun_end)
>  
>       /* 1:1 mapping */
>       for (i = 0; i < rrpc->nr_luns; i++) {
> -             struct nvm_lun *lun = dev->mt->get_lun(dev, lun_begin + i);
> +             int lunid = lun_begin + i;
> +             struct nvm_lun *lun;
>  
> -             rlun = &rrpc->luns[i];
> -             rlun->rrpc = rrpc;
> -             rlun->parent = lun;
> -             INIT_LIST_HEAD(&rlun->prio_list);
> -             INIT_LIST_HEAD(&rlun->open_list);
> -             INIT_LIST_HEAD(&rlun->closed_list);
> -
> -             INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
> -             spin_lock_init(&rlun->lock);
> +             if (dev->mt->reserve_lun(dev, lunid)) {
> +                     pr_err("rrpc: lun %u is already allocated\n", lunid);
> +                     goto err;
> +             }
>  
> -             rrpc->total_blocks += dev->blks_per_lun;
> -             rrpc->nr_sects += dev->sec_per_lun;
> +             lun = dev->mt->get_lun(dev, lunid);
> +             if (!lun)
> +                     goto err;
>  
> +             rlun = &rrpc->luns[i];
> +             rlun->parent = lun;
>               rlun->blocks = vzalloc(sizeof(struct rrpc_block) *
>                                               rrpc->dev->blks_per_lun);
> -             if (!rlun->blocks)
> +             if (!rlun->blocks) {
> +                     ret = -ENOMEM;
>                       goto err;
> +             }
>  
>               for (j = 0; j < rrpc->dev->blks_per_lun; j++) {
>                       struct rrpc_block *rblk = &rlun->blocks[j];
> @@ -1180,11 +1197,23 @@ static int rrpc_luns_init(struct rrpc *rrpc, int 
> lun_begin, int lun_end)
>                       INIT_LIST_HEAD(&rblk->prio);
>                       spin_lock_init(&rblk->lock);
>               }
> +
> +             rlun->rrpc = rrpc;
> +             INIT_LIST_HEAD(&rlun->prio_list);
> +             INIT_LIST_HEAD(&rlun->open_list);
> +             INIT_LIST_HEAD(&rlun->closed_list);
> +
> +             INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
> +             spin_lock_init(&rlun->lock);
> +
> +             rrpc->total_blocks += dev->blks_per_lun;
> +             rrpc->nr_sects += dev->sec_per_lun;
> +
>       }
>  
>       return 0;
>  err:
> -     return -ENOMEM;
> +     return ret;
>  }
>  
>  /* returns 0 on success and stores the beginning address in *begin */
> diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
> index ce58ad5..2a17dc1 100644
> --- a/include/linux/lightnvm.h
> +++ b/include/linux/lightnvm.h
> @@ -342,6 +342,7 @@ struct nvm_dev {
>       int nr_luns;
>       unsigned max_pages_per_blk;
>  
> +     unsigned long *lun_map;
>       void *ppalist_pool;
>  
>       struct nvm_id identity;
> @@ -462,6 +463,8 @@ typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct 
> nvm_rq *);
>  typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
>                                                               unsigned long);
>  typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int);
> +typedef int (nvmm_reserve_lun)(struct nvm_dev *, int);
> +typedef void (nvmm_release_lun)(struct nvm_dev *, int);
>  typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *);
>  
>  typedef int (nvmm_get_area_fn)(struct nvm_dev *, sector_t *, sector_t);
> @@ -488,6 +491,8 @@ struct nvmm_type {
>  
>       /* Configuration management */
>       nvmm_get_lun_fn *get_lun;
> +     nvmm_reserve_lun *reserve_lun;
> +     nvmm_release_lun *release_lun;
>  
>       /* Statistics */
>       nvmm_lun_info_print_fn *lun_info_print;
> 
Thanks, applied for 4.6. I added an extra kfree(dev->lun_map) at the end
of nvm_core_init to make sure that we freed the lun_map if other
allocations fails in initialization.

Reply via email to