mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Matias Bjørling" <mb@lightnvm.io>
To: Heiner Litz <hlitz@ucsc.edu>
Cc: javier@javigon.com, hans.holmberg@cnexlabs.com,
	linux-block@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH V2] lightnvm: pblk: fix race condition on GC
Date: Tue, 5 Feb 2019 10:14:59 +0100	[thread overview]
Message-ID: <79e30230-2af4-2fd4-f6ee-35e47c36291c@lightnvm.io> (raw)
In-Reply-To: <20190201023806.39895-1-hlitz@ucsc.edu>

On 2/1/19 3:38 AM, Heiner Litz wrote:
> This patch fixes a race condition where a write is mapped to the last
> sectors of a line. The write is synced to the device but the L2P is not
> updated yet. When the line is garbage collected before the L2P update is
> performed, the sectors are ignored by the GC logic and the line is freed
> before all sectors are moved. When the L2P is finally updated, it contains
> a mapping to a freed line, subsequent reads of the corresponding LBAs fail.
> 
> This patch introduces a per line counter specifying the number of sectors
> that are synced to the device but have not been updated in the L2P. Lines
> with a counter of greater than zero will not be selected for GC.
> 
> Signed-off-by: Heiner Litz <hlitz@ucsc.edu>
> ---
> 
> v2: changed according to Javier's comment. Instead of performing check
> while holding the trans_lock, add an atomic per line counter
> 
>   drivers/lightnvm/pblk-core.c  |  1 +
>   drivers/lightnvm/pblk-gc.c    | 20 +++++++++++++-------
>   drivers/lightnvm/pblk-map.c   |  1 +
>   drivers/lightnvm/pblk-rb.c    |  1 +
>   drivers/lightnvm/pblk-write.c |  1 +
>   drivers/lightnvm/pblk.h       |  1 +
>   6 files changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c
> index eabcbc119681..b7ed0502abef 100644
> --- a/drivers/lightnvm/pblk-core.c
> +++ b/drivers/lightnvm/pblk-core.c
> @@ -1278,6 +1278,7 @@ static int pblk_line_prepare(struct pblk *pblk, struct pblk_line *line)
>   	spin_unlock(&line->lock);
>   
>   	kref_init(&line->ref);
> +	atomic_set(&line->sec_to_update, 0);
>   
>   	return 0;
>   }
> diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
> index 2fa118c8eb71..26a52ea7ec45 100644
> --- a/drivers/lightnvm/pblk-gc.c
> +++ b/drivers/lightnvm/pblk-gc.c
> @@ -365,16 +365,22 @@ static struct pblk_line *pblk_gc_get_victim_line(struct pblk *pblk,
>   						 struct list_head *group_list)
>   {
>   	struct pblk_line *line, *victim;
> -	int line_vsc, victim_vsc;
> +	unsigned int line_vsc = ~0x0L, victim_vsc = ~0x0L;
>   
>   	victim = list_first_entry(group_list, struct pblk_line, list);
> +
>   	list_for_each_entry(line, group_list, list) {
> -		line_vsc = le32_to_cpu(*line->vsc);
> -		victim_vsc = le32_to_cpu(*victim->vsc);
> -		if (line_vsc < victim_vsc)
> +		if (!atomic_read(&line->sec_to_update))
> +			line_vsc = le32_to_cpu(*line->vsc);
> +		if (line_vsc < victim_vsc) {
>   			victim = line;
> +			victim_vsc = le32_to_cpu(*victim->vsc);
> +		}
>   	}
>   
> +	if (victim_vsc == ~0x0)
> +		return NULL;
> +
>   	return victim;
>   }
>   
> @@ -448,13 +454,13 @@ static void pblk_gc_run(struct pblk *pblk)
>   
>   	do {
>   		spin_lock(&l_mg->gc_lock);
> -		if (list_empty(group_list)) {
> +
> +		line = pblk_gc_get_victim_line(pblk, group_list);
> +		if (!line) {
>   			spin_unlock(&l_mg->gc_lock);
>   			break;
>   		}
>   
> -		line = pblk_gc_get_victim_line(pblk, group_list);
> -
>   		spin_lock(&line->lock);
>   		WARN_ON(line->state != PBLK_LINESTATE_CLOSED);
>   		line->state = PBLK_LINESTATE_GC;
> diff --git a/drivers/lightnvm/pblk-map.c b/drivers/lightnvm/pblk-map.c
> index 79df583ea709..7fbc99b60cac 100644
> --- a/drivers/lightnvm/pblk-map.c
> +++ b/drivers/lightnvm/pblk-map.c
> @@ -73,6 +73,7 @@ static int pblk_map_page_data(struct pblk *pblk, unsigned int sentry,
>   		 */
>   		if (i < valid_secs) {
>   			kref_get(&line->ref);
> +			atomic_inc(&line->sec_to_update);
>   			w_ctx = pblk_rb_w_ctx(&pblk->rwb, sentry + i);
>   			w_ctx->ppa = ppa_list[i];
>   			meta->lba = cpu_to_le64(w_ctx->lba);
> diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
> index a6133b50ed9c..03c241b340ea 100644
> --- a/drivers/lightnvm/pblk-rb.c
> +++ b/drivers/lightnvm/pblk-rb.c
> @@ -260,6 +260,7 @@ static int __pblk_rb_update_l2p(struct pblk_rb *rb, unsigned int to_update)
>   							entry->cacheline);
>   
>   		line = pblk_ppa_to_line(pblk, w_ctx->ppa);
> +		atomic_dec(&line->sec_to_update);
>   		kref_put(&line->ref, pblk_line_put);
>   		clean_wctx(w_ctx);
>   		rb->l2p_update = pblk_rb_ptr_wrap(rb, rb->l2p_update, 1);
> diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c
> index 06d56deb645d..6593deab52da 100644
> --- a/drivers/lightnvm/pblk-write.c
> +++ b/drivers/lightnvm/pblk-write.c
> @@ -177,6 +177,7 @@ static void pblk_prepare_resubmit(struct pblk *pblk, unsigned int sentry,
>   		 * re-map these entries
>   		 */
>   		line = pblk_ppa_to_line(pblk, w_ctx->ppa);
> +		atomic_dec(&line->sec_to_update);
>   		kref_put(&line->ref, pblk_line_put);
>   	}
>   	spin_unlock(&pblk->trans_lock);
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index a6386d5acd73..ac3ab778e976 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -487,6 +487,7 @@ struct pblk_line {
>   	__le32 *vsc;			/* Valid sector count in line */
>   
>   	struct kref ref;		/* Write buffer L2P references */
> +	atomic_t sec_to_update;         /* Outstanding L2P updates to ppa */
>   
>   	struct pblk_w_err_gc *w_err_gc;	/* Write error gc recovery metadata */
>   
> 

Thanks Heiner. Applied for 5.1.

      parent reply	other threads:[~2019-02-05  9:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-01  2:38 Heiner Litz
2019-02-04  8:19 ` Javier González
2019-02-04 21:01   ` Hans Holmberg
2019-02-05  9:14 ` Matias Bjørling [this message]

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=79e30230-2af4-2fd4-f6ee-35e47c36291c@lightnvm.io \
    --to=mb@lightnvm.io \
    --cc=hans.holmberg@cnexlabs.com \
    --cc=hlitz@ucsc.edu \
    --cc=javier@javigon.com \
    --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®