mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Matias Bjørling" <mb@lightnvm.io>
To: "Javier González" <jg@lightnvm.io>
Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Javier González" <javier@cnexlabs.com>
Subject: Re: [PATCH 5/5] lightnvm: pblk: refactor bad block identification
Date: Wed, 31 Jan 2018 09:51:50 +0100	[thread overview]
Message-ID: <bdde0655-0904-0bf1-7029-51708fcff8b3@lightnvm.io> (raw)
In-Reply-To: <1517364411-22386-5-git-send-email-javier@cnexlabs.com>

On 01/31/2018 03:06 AM, Javier González wrote:
> In preparation for the OCSSD 2.0 spec. bad block identification,
> refactor the current code to generalize bad block get/set functions and
> structures.
> 
> Signed-off-by: Javier González <javier@cnexlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c | 213 +++++++++++++++++++++++--------------------
>   drivers/lightnvm/pblk.h      |   6 --
>   2 files changed, 112 insertions(+), 107 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index a5e3510c0f38..86a94a7faa96 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -365,7 +365,25 @@ static void pblk_luns_free(struct pblk *pblk)
>   	kfree(pblk->luns);
>   }
>   
> -static void pblk_free_line_bitmaps(struct pblk_line *line)
> +static void pblk_line_mg_free(struct pblk *pblk)
> +{
> +	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> +	int i;
> +
> +	kfree(l_mg->bb_template);
> +	kfree(l_mg->bb_aux);
> +	kfree(l_mg->vsc_list);
> +
> +	for (i = 0; i < PBLK_DATA_LINES; i++) {
> +		kfree(l_mg->sline_meta[i]);
> +		pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
> +		kfree(l_mg->eline_meta[i]);
> +	}
> +
> +	kfree(pblk->lines);
> +}
> +
> +static void pblk_line_meta_free(struct pblk_line *line)
>   {
>   	kfree(line->blk_bitmap);
>   	kfree(line->erase_bitmap);
> @@ -382,40 +400,16 @@ static void pblk_lines_free(struct pblk *pblk)
>   		line = &pblk->lines[i];
>   
>   		pblk_line_free(pblk, line);
> -		pblk_free_line_bitmaps(line);
> +		pblk_line_meta_free(line);
>   	}
>   	spin_unlock(&l_mg->free_lock);
>   }
>   
> -static void pblk_line_meta_free(struct pblk *pblk)
> +static int pblk_bb_get_tbl(struct nvm_tgt_dev *dev, struct pblk_lun *rlun,
> +			   u8 *blks, int nr_blks)
>   {
> -	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
> -	int i;
> -
> -	kfree(l_mg->bb_template);
> -	kfree(l_mg->bb_aux);
> -	kfree(l_mg->vsc_list);
> -
> -	for (i = 0; i < PBLK_DATA_LINES; i++) {
> -		kfree(l_mg->sline_meta[i]);
> -		pblk_mfree(l_mg->eline_meta[i]->buf, l_mg->emeta_alloc_type);
> -		kfree(l_mg->eline_meta[i]);
> -	}
> -
> -	kfree(pblk->lines);
> -}
> -
> -static int pblk_bb_discovery(struct nvm_tgt_dev *dev, struct pblk_lun *rlun)
> -{
> -	struct nvm_geo *geo = &dev->geo;
>   	struct ppa_addr ppa;
> -	u8 *blks;
> -	int nr_blks, ret;
> -
> -	nr_blks = geo->nr_chks * geo->plane_mode;
> -	blks = kmalloc(nr_blks, GFP_KERNEL);
> -	if (!blks)
> -		return -ENOMEM;
> +	int ret;
>   
>   	ppa.ppa = 0;
>   	ppa.g.ch = rlun->bppa.g.ch;
> @@ -423,34 +417,56 @@ static int pblk_bb_discovery(struct nvm_tgt_dev *dev, struct pblk_lun *rlun)
>   
>   	ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
>   	if (ret)
> -		goto out;
> +		return ret;
>   
>   	nr_blks = nvm_bb_tbl_fold(dev->parent, blks, nr_blks);
> -	if (nr_blks < 0) {
> -		ret = nr_blks;
> -		goto out;
> -	}
> -
> -	rlun->bb_list = blks;
> +	if (nr_blks < 0)
> +		return -EIO;
>   
>   	return 0;
> -out:
> -	kfree(blks);
> -	return ret;
> +}
> +
> +static void *pblk_bb_get_log(struct pblk *pblk)
> +{
> +	struct nvm_tgt_dev *dev = pblk->dev;
> +	struct nvm_geo *geo = &dev->geo;
> +	u8 *log;
> +	int i, nr_blks, blk_per_lun;
> +	int ret;
> +
> +	blk_per_lun = geo->nr_chks * geo->plane_mode;
> +	nr_blks = blk_per_lun * geo->all_luns;
> +
> +	log = kmalloc(nr_blks, GFP_KERNEL);
> +	if (!log)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < geo->all_luns; i++) {
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		u8 *log_pos = log + i * blk_per_lun;
> +
> +		ret = pblk_bb_get_tbl(dev, rlun, log_pos, blk_per_lun);
> +		if (ret) {
> +			kfree(log);
> +			return ERR_PTR(-EIO);
> +		}
> +	}
> +
> +	return log;
>   }
>   
>   static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
> -			int blk_per_line)
> +			u8 *bb_log, int blk_per_line)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
> -	struct pblk_lun *rlun;
> -	int bb_cnt = 0;
> -	int i;
> +	int i, bb_cnt = 0;
>   
>   	for (i = 0; i < blk_per_line; i++) {
> -		rlun = &pblk->luns[i];
> -		if (rlun->bb_list[line->id] == NVM_BLK_T_FREE)
> +		struct pblk_lun *rlun = &pblk->luns[i];
> +		u8 *lun_bb_log = bb_log + i * blk_per_line;
> +
> +		if (lun_bb_log[line->id] == NVM_BLK_T_FREE)
>   			continue;
>   
>   		set_bit(pblk_ppa_to_pos(geo, rlun->bppa), line->blk_bitmap);
> @@ -460,29 +476,12 @@ static int pblk_bb_line(struct pblk *pblk, struct pblk_line *line,
>   	return bb_cnt;
>   }
>   
> -static int pblk_alloc_line_bitmaps(struct pblk *pblk, struct pblk_line *line)
> -{
> -	struct pblk_line_meta *lm = &pblk->lm;
> -
> -	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
> -	if (!line->blk_bitmap)
> -		return -ENOMEM;
> -
> -	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
> -	if (!line->erase_bitmap) {
> -		kfree(line->blk_bitmap);
> -		return -ENOMEM;
> -	}
> -
> -	return 0;
> -}
> -
>   static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   	struct pblk_lun *rlun;
> -	int i, ret;
> +	int i;
>   
>   	/* TODO: Implement unbalanced LUN support */
>   	if (geo->nr_luns < 0) {
> @@ -505,13 +504,6 @@ static int pblk_luns_init(struct pblk *pblk, struct ppa_addr *luns)
>   		rlun->bppa = luns[lunid];
>   
>   		sema_init(&rlun->wr_sem, 1);
> -
> -		ret = pblk_bb_discovery(dev, rlun);
> -		if (ret) {
> -			while (--i >= 0)
> -				kfree(pblk->luns[i].bb_list);
> -			return ret;
> -		}
>   	}
>   
>   	return 0;
> @@ -689,6 +681,26 @@ static int pblk_lines_alloc_metadata(struct pblk *pblk)
>   	return -ENOMEM;
>   }
>   
> +static int pblk_setup_line_meta(struct pblk *pblk, struct pblk_line *line,
> +				void *chunk_log, long *nr_bad_blks)
> +{
> +	struct pblk_line_meta *lm = &pblk->lm;
> +
> +	line->blk_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
> +	if (!line->blk_bitmap)
> +		return -ENOMEM;
> +
> +	line->erase_bitmap = kzalloc(lm->blk_bitmap_len, GFP_KERNEL);
> +	if (!line->erase_bitmap) {
> +		kfree(line->blk_bitmap);
> +		return -ENOMEM;
> +	}
> +
> +	*nr_bad_blks = pblk_bb_line(pblk, line, chunk_log, lm->blk_per_line);
> +
> +	return 0;
> +}
> +
>   static int pblk_lines_init(struct pblk *pblk)
>   {
>   	struct nvm_tgt_dev *dev = pblk->dev;
> @@ -696,8 +708,9 @@ static int pblk_lines_init(struct pblk *pblk)
>   	struct pblk_line_mgmt *l_mg = &pblk->l_mg;
>   	struct pblk_line_meta *lm = &pblk->lm;
>   	struct pblk_line *line;
> +	void *chunk_log;
>   	unsigned int smeta_len, emeta_len;
> -	long nr_bad_blks, nr_free_blks;
> +	long nr_bad_blks = 0, nr_free_blks = 0;
>   	int bb_distance, max_write_ppas, mod;
>   	int i, ret;
>   
> @@ -771,13 +784,12 @@ static int pblk_lines_init(struct pblk *pblk)
>   	if (lm->min_blk_line > lm->blk_per_line) {
>   		pr_err("pblk: config. not supported. Min. LUN in line:%d\n",
>   							lm->blk_per_line);
> -		ret = -EINVAL;
> -		goto fail;
> +		return -EINVAL;
>   	}
>   
>   	ret = pblk_lines_alloc_metadata(pblk);
>   	if (ret)
> -		goto fail;
> +		return ret;
>   
>   	l_mg->bb_template = kzalloc(lm->sec_bitmap_len, GFP_KERNEL);
>   	if (!l_mg->bb_template) {
> @@ -821,9 +833,16 @@ static int pblk_lines_init(struct pblk *pblk)
>   		goto fail_free_bb_aux;
>   	}
>   
> -	nr_free_blks = 0;
> +	chunk_log = pblk_bb_get_log(pblk);
> +	if (IS_ERR(chunk_log)) {
> +		pr_err("pblk: could not get bad block log (%lu)\n",
> +							PTR_ERR(chunk_log));
> +		ret = PTR_ERR(chunk_log);
> +		goto fail_free_lines;
> +	}
> +
>   	for (i = 0; i < l_mg->nr_lines; i++) {
> -		int blk_in_line;
> +		int chk_in_line;
>   
>   		line = &pblk->lines[i];
>   
> @@ -835,26 +854,20 @@ static int pblk_lines_init(struct pblk *pblk)
>   		line->vsc = &l_mg->vsc_list[i];
>   		spin_lock_init(&line->lock);
>   
> -		ret = pblk_alloc_line_bitmaps(pblk, line);
> +		ret = pblk_setup_line_meta(pblk, line, chunk_log, &nr_bad_blks);
>   		if (ret)
> -			goto fail_free_lines;
> +			goto fail_free_chunk_log;
>   
> -		nr_bad_blks = pblk_bb_line(pblk, line, lm->blk_per_line);
> -		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line) {
> -			pblk_free_line_bitmaps(line);
> -			ret = -EINVAL;
> -			goto fail_free_lines;
> -		}
> -
> -		blk_in_line = lm->blk_per_line - nr_bad_blks;
> -		if (blk_in_line < lm->min_blk_line) {
> +		chk_in_line = lm->blk_per_line - nr_bad_blks;
> +		if (nr_bad_blks < 0 || nr_bad_blks > lm->blk_per_line ||
> +					chk_in_line < lm->min_blk_line) {
>   			line->state = PBLK_LINESTATE_BAD;
>   			list_add_tail(&line->list, &l_mg->bad_list);
>   			continue;
>   		}
>   
> -		nr_free_blks += blk_in_line;
> -		atomic_set(&line->blk_in_line, blk_in_line);
> +		nr_free_blks += chk_in_line;
> +		atomic_set(&line->blk_in_line, chk_in_line);
>   
>   		l_mg->nr_free_lines++;
>   		list_add_tail(&line->list, &l_mg->free_list);
> @@ -862,23 +875,21 @@ static int pblk_lines_init(struct pblk *pblk)
>   
>   	pblk_set_provision(pblk, nr_free_blks);
>   
> -	/* Cleanup per-LUN bad block lists - managed within lines on run-time */
> -	for (i = 0; i < geo->all_luns; i++)
> -		kfree(pblk->luns[i].bb_list);
> -
> +	kfree(chunk_log);
>   	return 0;
> -fail_free_lines:
> +
> +fail_free_chunk_log:
> +	kfree(chunk_log);
>   	while (--i >= 0)
> -		pblk_free_line_bitmaps(&pblk->lines[i]);
> +		pblk_line_meta_free(&pblk->lines[i]);
> +fail_free_lines:
> +	kfree(pblk->lines);
>   fail_free_bb_aux:
>   	kfree(l_mg->bb_aux);
>   fail_free_bb_template:
>   	kfree(l_mg->bb_template);
>   fail_free_meta:
> -	pblk_line_meta_free(pblk);
> -fail:
> -	for (i = 0; i < geo->all_luns; i++)
> -		kfree(pblk->luns[i].bb_list);
> +	pblk_line_mg_free(pblk);
>   
>   	return ret;
>   }
> @@ -922,7 +933,7 @@ static void pblk_free(struct pblk *pblk)
>   	pblk_luns_free(pblk);
>   	pblk_lines_free(pblk);
>   	kfree(pblk->pad_dist);
> -	pblk_line_meta_free(pblk);
> +	pblk_line_mg_free(pblk);
>   	pblk_core_free(pblk);
>   	pblk_l2p_free(pblk);
>   
> @@ -1110,7 +1121,7 @@ static void *pblk_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk,
>   fail_free_pad_dist:
>   	kfree(pblk->pad_dist);
>   fail_free_line_meta:
> -	pblk_line_meta_free(pblk);
> +	pblk_line_mg_free(pblk);
>   fail_free_luns:
>   	pblk_luns_free(pblk);
>   fail:
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 88720e2441c0..282dfc8780e8 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -201,12 +201,6 @@ struct pblk_rb {
>   
>   struct pblk_lun {
>   	struct ppa_addr bppa;
> -
> -	u8 *bb_list;			/* Bad block list for LUN. Only used on
> -					 * bring up. Bad blocks are managed
> -					 * within lines on run-time.
> -					 */
> -
>   	struct semaphore wr_sem;
>   };
>   
> 

Looks good to me.

With respect to the 2.0 implementation. I am thinking that get_bb and 
set_bb should behave in the following way:

For get_bb (in nvme/host/lightnvm.c)
1.2: Keep the implementation as is.
2.0: Use the report chunk command, and redo the get_bb format.

For set_bb (in nvme/host/lightnvm.c)
1.2: Business as usual
2.0: Report error.

For 2.0, there will be added a function pointer for get report chunk 
implementation, where the client can ask for full chunk information. 
Similarly here, client will fail the function call if the drive is 1.2.

I hope to post the small 2.0 identify implementation Tomorrow or Friday, 
and then you can post the report chunk implementation that you have done 
if you like.

We also need to take a look at the new error codes, which does not align 
with the 1.2 specification (now that they actually follow the nvme 
specification ;))

  reply	other threads:[~2018-01-31  8:51 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-31  2:06 [PATCH 1/5] lightnvm: pblk: handle bad sectors in the emeta area correctly Javier González
2018-01-31  2:06 ` [PATCH 2/5] lightnvm: pblk: check data lines version on recovery Javier González
2018-01-31  2:06 ` [PATCH 3/5] lightnvm: pblk: export write amplification counters to sysfs Javier González
2018-01-31  2:06 ` [PATCH 4/5] lightnvm: pblk: add padding distribution sysfs attribute Javier González
2018-01-31  8:44   ` Matias Bjørling
2018-02-06  9:27     ` Hans Holmberg
2018-02-06 10:50       ` Matias Bjørling
2018-02-06 11:28         ` Hans Holmberg
2018-01-31  2:06 ` [PATCH 5/5] lightnvm: pblk: refactor bad block identification Javier González
2018-01-31  8:51   ` Matias Bjørling [this message]
2018-01-31  9:13     ` Javier Gonzalez
2018-01-31 18:24       ` Matias Bjørling
2018-02-04 10:37         ` Javier Gonzalez
2018-02-04 12:54           ` Matias Bjørling
2018-02-04 13:09             ` Javier Gonzalez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bdde0655-0904-0bf1-7029-51708fcff8b3@lightnvm.io \
    --to=mb@lightnvm.io \
    --cc=javier@cnexlabs.com \
    --cc=jg@lightnvm.io \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®