aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/core.c
diff options
context:
space:
mode:
authorMatias Bjørling <m@bjorling.me>2016-05-06 14:02:59 -0400
committerJens Axboe <axboe@fb.com>2016-05-06 14:51:10 -0400
commit7f7c5d03c0e8e177d1ed1c6412ae035e8eff35de (patch)
tree1a354500001df077c63e14ba63c29fc43d375fcf /drivers/lightnvm/core.c
parent22e8c9766a669d49cf3749d397082a5cd93374a9 (diff)
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>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r--drivers/lightnvm/core.c53
1 files 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)
504{ 504{
505 struct nvm_id *id = &dev->identity; 505 struct nvm_id *id = &dev->identity;
506 struct nvm_id_group *grp = &id->groups[0]; 506 struct nvm_id_group *grp = &id->groups[0];
507 int ret;
507 508
508 /* device values */ 509 /* device values */
509 dev->nr_chnls = grp->num_ch; 510 dev->nr_chnls = grp->num_ch;
@@ -522,33 +523,16 @@ static int nvm_core_init(struct nvm_dev *dev)
522 dev->plane_mode = NVM_PLANE_SINGLE; 523 dev->plane_mode = NVM_PLANE_SINGLE;
523 dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size; 524 dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size;
524 525
525 if (grp->mtype != 0) {
526 pr_err("nvm: memory type not supported\n");
527 return -EINVAL;
528 }
529
530 switch (grp->fmtype) {
531 case NVM_ID_FMTYPE_SLC:
532 if (nvm_init_slc_tbl(dev, grp))
533 return -ENOMEM;
534 break;
535 case NVM_ID_FMTYPE_MLC:
536 if (nvm_init_mlc_tbl(dev, grp))
537 return -ENOMEM;
538 break;
539 default:
540 pr_err("nvm: flash type not supported\n");
541 return -EINVAL;
542 }
543
544 if (!dev->lps_per_blk)
545 pr_info("nvm: lower page programming table missing\n");
546
547 if (grp->mpos & 0x020202) 526 if (grp->mpos & 0x020202)
548 dev->plane_mode = NVM_PLANE_DOUBLE; 527 dev->plane_mode = NVM_PLANE_DOUBLE;
549 if (grp->mpos & 0x040404) 528 if (grp->mpos & 0x040404)
550 dev->plane_mode = NVM_PLANE_QUAD; 529 dev->plane_mode = NVM_PLANE_QUAD;
551 530
531 if (grp->mtype != 0) {
532 pr_err("nvm: memory type not supported\n");
533 return -EINVAL;
534 }
535
552 /* calculated values */ 536 /* calculated values */
553 dev->sec_per_pl = dev->sec_per_pg * dev->nr_planes; 537 dev->sec_per_pl = dev->sec_per_pg * dev->nr_planes;
554 dev->sec_per_blk = dev->sec_per_pl * dev->pgs_per_blk; 538 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)
560 sizeof(unsigned long), GFP_KERNEL); 544 sizeof(unsigned long), GFP_KERNEL);
561 if (!dev->lun_map) 545 if (!dev->lun_map)
562 return -ENOMEM; 546 return -ENOMEM;
547
548 switch (grp->fmtype) {
549 case NVM_ID_FMTYPE_SLC:
550 if (nvm_init_slc_tbl(dev, grp)) {
551 ret = -ENOMEM;
552 goto err_fmtype;
553 }
554 break;
555 case NVM_ID_FMTYPE_MLC:
556 if (nvm_init_mlc_tbl(dev, grp)) {
557 ret = -ENOMEM;
558 goto err_fmtype;
559 }
560 break;
561 default:
562 pr_err("nvm: flash type not supported\n");
563 ret = -EINVAL;
564 goto err_fmtype;
565 }
566
563 INIT_LIST_HEAD(&dev->online_targets); 567 INIT_LIST_HEAD(&dev->online_targets);
564 mutex_init(&dev->mlock); 568 mutex_init(&dev->mlock);
565 spin_lock_init(&dev->lock); 569 spin_lock_init(&dev->lock);
566 570
567 return 0; 571 return 0;
572err_fmtype:
573 kfree(dev->lun_map);
574 return ret;
568} 575}
569 576
570static void nvm_free(struct nvm_dev *dev) 577static void nvm_free(struct nvm_dev *dev)
@@ -576,6 +583,7 @@ static void nvm_free(struct nvm_dev *dev)
576 dev->mt->unregister_mgr(dev); 583 dev->mt->unregister_mgr(dev);
577 584
578 kfree(dev->lptbl); 585 kfree(dev->lptbl);
586 kfree(dev->lun_map);
579} 587}
580 588
581static int nvm_init(struct nvm_dev *dev) 589static int nvm_init(struct nvm_dev *dev)
@@ -705,7 +713,6 @@ void nvm_unregister(char *disk_name)
705 up_write(&nvm_lock); 713 up_write(&nvm_lock);
706 714
707 nvm_exit(dev); 715 nvm_exit(dev);
708 kfree(dev->lun_map);
709 kfree(dev); 716 kfree(dev);
710} 717}
711EXPORT_SYMBOL(nvm_unregister); 718EXPORT_SYMBOL(nvm_unregister);