lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Sat, 6 Oct 2018 03:05:08 +0200
From:   Matias Bjørling <mb@...htnvm.io>
To:     javier@...igon.com
Cc:     hlitz@...c.edu, linux-block@...r.kernel.org,
        linux-kernel@...r.kernel.org, javier@...xlabs.com
Subject: Re: [PATCH] lightnvm: pblk: guarantee that backpointer is respected
 on writer stall

On 10/04/2018 09:26 AM, Javier González wrote:
> pblk's write buffer must guarantee that it respects the device's
> constrains for reads (i.e., mw_cunits). This is done by maintaining a
> backpointer that updates the L2P table as entries wrap up, making them
> point to the media instead of pointing to the write buffer.
> 
> This mechanism can race in case that the write thread stalls, as the
> write pointer will protect the last written entry, thus disregarding the
> read constrains.
> 
> This patch adds an extra check on wrap up, making sure that the
> threshold is respected at all times, preventing new entries to overwrite
> committed data, also in case of write thread stall.
> 
> Reported-by: Heiner Litz <hlitz@...c.edu>
> Signed-off-by: Javier González <javier@...xlabs.com>
> ---
>   drivers/lightnvm/pblk-init.c | 5 +++--
>   drivers/lightnvm/pblk-rb.c   | 9 +++++++--
>   drivers/lightnvm/pblk.h      | 8 +++++++-
>   3 files changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index e3573880dbda..deaeb4649294 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -193,8 +193,9 @@ static int pblk_rwb_init(struct pblk *pblk)
>   	struct nvm_tgt_dev *dev = pblk->dev;
>   	struct nvm_geo *geo = &dev->geo;
>   	unsigned long buffer_size;
> -	int pgs_in_buffer;
> +	int pgs_in_buffer, threshold;
>   
> +	threshold = geo->mw_cunits * geo->all_luns;
>   	pgs_in_buffer = (max(geo->mw_cunits, geo->ws_opt) + geo->ws_opt)
>   								* geo->all_luns;
>   
> @@ -203,7 +204,7 @@ static int pblk_rwb_init(struct pblk *pblk)
>   	else
>   		buffer_size = pgs_in_buffer;
>   
> -	return pblk_rb_init(&pblk->rwb, buffer_size, geo->csecs);
> +	return pblk_rb_init(&pblk->rwb, buffer_size, threshold, geo->csecs);
>   }
>   
>   /* Minimum pages needed within a lun */
> diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
> index f653faa6a9ed..b1f4b51783f4 100644
> --- a/drivers/lightnvm/pblk-rb.c
> +++ b/drivers/lightnvm/pblk-rb.c
> @@ -56,7 +56,8 @@ static unsigned int pblk_rb_calculate_size(unsigned int nr_entries)
>    * allocated and their size must be a power of two
>    * (Documentation/core-api/circular-buffers.rst)
>    */
> -int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int seg_size)
> +int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int threshold,
> +		 unsigned int seg_size)
>   {
>   	struct pblk *pblk = container_of(rb, struct pblk, rwb);
>   	struct pblk_rb_entry *entries;
> @@ -79,6 +80,7 @@ int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int seg_size)
>   	rb->seg_size = (1 << power_seg_sz);
>   	rb->nr_entries = (1 << power_size);
>   	rb->mem = rb->subm = rb->sync = rb->l2p_update = 0;
> +	rb->back_thres = threshold;
>   	rb->flush_point = EMPTY_ENTRY;
>   
>   	spin_lock_init(&rb->w_lock);
> @@ -404,11 +406,14 @@ static int __pblk_rb_may_write(struct pblk_rb *rb, unsigned int nr_entries,
>   {
>   	unsigned int mem;
>   	unsigned int sync;
> +	unsigned int threshold;
>   
>   	sync = READ_ONCE(rb->sync);
>   	mem = READ_ONCE(rb->mem);
>   
> -	if (pblk_rb_ring_space(rb, mem, sync, rb->nr_entries) < nr_entries)
> +	threshold = nr_entries + rb->back_thres;
> +
> +	if (pblk_rb_ring_space(rb, mem, sync, rb->nr_entries) < threshold)
>   		return 0;
>   
>   	if (pblk_rb_update_l2p(rb, nr_entries, mem, sync))
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 34c9c1dbeed9..c1665e39829d 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -203,6 +203,11 @@ struct pblk_rb {
>   					 * will be 4KB
>   					 */
>   
> +	unsigned int back_thres;	/* Threshold that shall be maintained by
> +					 * the backpointer in order to respect
> +					 * geo->mw_cunits on a per chunk basis
> +					 */
> +
>   	struct list_head pages;		/* List of data pages */
>   
>   	spinlock_t w_lock;		/* Write lock */
> @@ -734,7 +739,8 @@ struct pblk_line_ws {
>   /*
>    * pblk ring buffer operations
>    */
> -int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int seg_sz);
> +int pblk_rb_init(struct pblk_rb *rb, unsigned int size, unsigned int threshold,
> +		 unsigned int seg_sz);
>   int pblk_rb_may_write_user(struct pblk_rb *rb, struct bio *bio,
>   			   unsigned int nr_entries, unsigned int *pos);
>   int pblk_rb_may_write_gc(struct pblk_rb *rb, unsigned int nr_entries,
> 

Thanks. Applied for 4.20.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ