lightnvm: avoid memory leak when lun_map kcalloc fails
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 <jthumshirn@suse.de> Move kfree of dev->lun_map to nvm_free() Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
Родитель
22e8c9766a
Коммит
7f7c5d03c0
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче