aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/pblk-init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lightnvm/pblk-init.c')
-rw-r--r--drivers/lightnvm/pblk-init.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 13822594647c..f083130d9920 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -635,7 +635,7 @@ static unsigned int calc_emeta_len(struct pblk *pblk)
635 return (lm->emeta_len[1] + lm->emeta_len[2] + lm->emeta_len[3]); 635 return (lm->emeta_len[1] + lm->emeta_len[2] + lm->emeta_len[3]);
636} 636}
637 637
638static void pblk_set_provision(struct pblk *pblk, long nr_free_blks) 638static int pblk_set_provision(struct pblk *pblk, int nr_free_chks)
639{ 639{
640 struct nvm_tgt_dev *dev = pblk->dev; 640 struct nvm_tgt_dev *dev = pblk->dev;
641 struct pblk_line_mgmt *l_mg = &pblk->l_mg; 641 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
@@ -643,23 +643,41 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
643 struct nvm_geo *geo = &dev->geo; 643 struct nvm_geo *geo = &dev->geo;
644 sector_t provisioned; 644 sector_t provisioned;
645 int sec_meta, blk_meta; 645 int sec_meta, blk_meta;
646 int minimum;
646 647
647 if (geo->op == NVM_TARGET_DEFAULT_OP) 648 if (geo->op == NVM_TARGET_DEFAULT_OP)
648 pblk->op = PBLK_DEFAULT_OP; 649 pblk->op = PBLK_DEFAULT_OP;
649 else 650 else
650 pblk->op = geo->op; 651 pblk->op = geo->op;
651 652
652 provisioned = nr_free_blks; 653 minimum = pblk_get_min_chks(pblk);
654 provisioned = nr_free_chks;
653 provisioned *= (100 - pblk->op); 655 provisioned *= (100 - pblk->op);
654 sector_div(provisioned, 100); 656 sector_div(provisioned, 100);
655 657
656 pblk->op_blks = nr_free_blks - provisioned; 658 if ((nr_free_chks - provisioned) < minimum) {
659 if (geo->op != NVM_TARGET_DEFAULT_OP) {
660 pblk_err(pblk, "OP too small to create a sane instance\n");
661 return -EINTR;
662 }
663
664 /* If the user did not specify an OP value, and PBLK_DEFAULT_OP
665 * is not enough, calculate and set sane value
666 */
667
668 provisioned = nr_free_chks - minimum;
669 pblk->op = (100 * minimum) / nr_free_chks;
670 pblk_info(pblk, "Default OP insufficient, adjusting OP to %d\n",
671 pblk->op);
672 }
673
674 pblk->op_blks = nr_free_chks - provisioned;
657 675
658 /* Internally pblk manages all free blocks, but all calculations based 676 /* Internally pblk manages all free blocks, but all calculations based
659 * on user capacity consider only provisioned blocks 677 * on user capacity consider only provisioned blocks
660 */ 678 */
661 pblk->rl.total_blocks = nr_free_blks; 679 pblk->rl.total_blocks = nr_free_chks;
662 pblk->rl.nr_secs = nr_free_blks * geo->clba; 680 pblk->rl.nr_secs = nr_free_chks * geo->clba;
663 681
664 /* Consider sectors used for metadata */ 682 /* Consider sectors used for metadata */
665 sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines; 683 sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
@@ -667,8 +685,10 @@ static void pblk_set_provision(struct pblk *pblk, long nr_free_blks)
667 685
668 pblk->capacity = (provisioned - blk_meta) * geo->clba; 686 pblk->capacity = (provisioned - blk_meta) * geo->clba;
669 687
670 atomic_set(&pblk->rl.free_blocks, nr_free_blks); 688 atomic_set(&pblk->rl.free_blocks, nr_free_chks);
671 atomic_set(&pblk->rl.free_user_blocks, nr_free_blks); 689 atomic_set(&pblk->rl.free_user_blocks, nr_free_chks);
690
691 return 0;
672} 692}
673 693
674static int pblk_setup_line_meta_chk(struct pblk *pblk, struct pblk_line *line, 694static int pblk_setup_line_meta_chk(struct pblk *pblk, struct pblk_line *line,
@@ -984,7 +1004,7 @@ static int pblk_lines_init(struct pblk *pblk)
984 struct pblk_line_mgmt *l_mg = &pblk->l_mg; 1004 struct pblk_line_mgmt *l_mg = &pblk->l_mg;
985 struct pblk_line *line; 1005 struct pblk_line *line;
986 void *chunk_meta; 1006 void *chunk_meta;
987 long nr_free_chks = 0; 1007 int nr_free_chks = 0;
988 int i, ret; 1008 int i, ret;
989 1009
990 ret = pblk_line_meta_init(pblk); 1010 ret = pblk_line_meta_init(pblk);
@@ -1031,7 +1051,9 @@ static int pblk_lines_init(struct pblk *pblk)
1031 goto fail_free_lines; 1051 goto fail_free_lines;
1032 } 1052 }
1033 1053
1034 pblk_set_provision(pblk, nr_free_chks); 1054 ret = pblk_set_provision(pblk, nr_free_chks);
1055 if (ret)
1056 goto fail_free_lines;
1035 1057
1036 vfree(chunk_meta); 1058 vfree(chunk_meta);
1037 return 0; 1059 return 0;