From 7f7c5d03c0e8e177d1ed1c6412ae035e8eff35de Mon Sep 17 00:00:00 2001 From: =?utf8?q?Matias=20Bj=C3=B8rling?= Date: Fri, 6 May 2016 20:02:59 +0200 Subject: [PATCH] lightnvm: avoid memory leak when lun_map kcalloc fails MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit A memory leak occurs if the lower page table is initialized and the following dev->lun_map fails on allocation. Rearrange the initialization of lower page table to allow dev->lun_map to fail gracefully without memory leak. Reviewed by: Johannes Thumshirn Move kfree of dev->lun_map to nvm_free() Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 53 +++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 4cadbe0cd537..74fb049e0b83 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -504,6 +504,7 @@ static int nvm_core_init(struct nvm_dev *dev) { struct nvm_id *id = &dev->identity; struct nvm_id_group *grp = &id->groups[0]; + int ret; /* device values */ dev->nr_chnls = grp->num_ch; @@ -522,33 +523,16 @@ static int nvm_core_init(struct nvm_dev *dev) dev->plane_mode = NVM_PLANE_SINGLE; dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size; - if (grp->mtype != 0) { - pr_err("nvm: memory type not supported\n"); - return -EINVAL; - } - - switch (grp->fmtype) { - case NVM_ID_FMTYPE_SLC: - if (nvm_init_slc_tbl(dev, grp)) - return -ENOMEM; - break; - case NVM_ID_FMTYPE_MLC: - if (nvm_init_mlc_tbl(dev, grp)) - return -ENOMEM; - break; - default: - pr_err("nvm: flash type not supported\n"); - return -EINVAL; - } - - if (!dev->lps_per_blk) - pr_info("nvm: lower page programming table missing\n"); - if (grp->mpos & 0x020202) dev->plane_mode = NVM_PLANE_DOUBLE; if (grp->mpos & 0x040404) dev->plane_mode = NVM_PLANE_QUAD; + if (grp->mtype != 0) { + pr_err("nvm: memory type not supported\n"); + return -EINVAL; + } + /* calculated values */ dev->sec_per_pl = dev->sec_per_pg * dev->nr_planes; dev->sec_per_blk = dev->sec_per_pl * dev->pgs_per_blk; @@ -560,11 +544,34 @@ static int nvm_core_init(struct nvm_dev *dev) sizeof(unsigned long), GFP_KERNEL); if (!dev->lun_map) return -ENOMEM; + + switch (grp->fmtype) { + case NVM_ID_FMTYPE_SLC: + if (nvm_init_slc_tbl(dev, grp)) { + ret = -ENOMEM; + goto err_fmtype; + } + break; + case NVM_ID_FMTYPE_MLC: + if (nvm_init_mlc_tbl(dev, grp)) { + ret = -ENOMEM; + goto err_fmtype; + } + break; + default: + pr_err("nvm: flash type not supported\n"); + ret = -EINVAL; + goto err_fmtype; + } + INIT_LIST_HEAD(&dev->online_targets); mutex_init(&dev->mlock); spin_lock_init(&dev->lock); return 0; +err_fmtype: + kfree(dev->lun_map); + return ret; } static void nvm_free(struct nvm_dev *dev) @@ -576,6 +583,7 @@ static void nvm_free(struct nvm_dev *dev) dev->mt->unregister_mgr(dev); kfree(dev->lptbl); + kfree(dev->lun_map); } static int nvm_init(struct nvm_dev *dev) @@ -705,7 +713,6 @@ void nvm_unregister(char *disk_name) up_write(&nvm_lock); nvm_exit(dev); - kfree(dev->lun_map); kfree(dev); } EXPORT_SYMBOL(nvm_unregister); -- 2.20.1