Re: [PATCH 1/2] bcache: fix race between setting bdev state to none and new write request direct to backing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2020/10/14 15:46, Dongsheng Yang wrote:
> There is a race condition in detaching as below:
> A. detaching						B. Write request
> (1) writing back
> (2) write back done, set bdev state to clean.
> (3) cached_dev_put() and schedule_work(&dc->detach);
> 							(4) write data [0 - 4K] directly into backing and ack to user.
> (5) power-failure...
> 
> When we restart this bcache device, this bdev is clean but not detached, and read [0 - 4K],
> we will get unexpected old data from cache device.
> 
> To fix this problem, set the bdev state to none when we writeback done in detaching,
> and then if power-failure happend as above, the data in cache will not be used in next
> bcache device starting, it's detached, we will read the correct data from backing derectly.
> 
> Signed-off-by: Dongsheng Yang <dongsheng.yang@xxxxxxxxxxxx>


Hi Dongsheng,

It takes me for a while to understand and make sure the whole code flow
works correctly. Thank you for catching such a very rare problem. IMHO
this patch is cool, I will add it into the for-test queue.

Thanks.

Coly Li


> ---
>  drivers/md/bcache/super.c     | 9 ---------
>  drivers/md/bcache/writeback.c | 9 +++++++++
>  2 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
> index 1bbdc41..9298fc7 100644
> --- a/drivers/md/bcache/super.c
> +++ b/drivers/md/bcache/super.c
> @@ -1128,9 +1128,6 @@ static void cancel_writeback_rate_update_dwork(struct cached_dev *dc)
>  static void cached_dev_detach_finish(struct work_struct *w)
>  {
>  	struct cached_dev *dc = container_of(w, struct cached_dev, detach);
> -	struct closure cl;
> -
> -	closure_init_stack(&cl);
>  
>  	BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
>  	BUG_ON(refcount_read(&dc->count));
> @@ -1144,12 +1141,6 @@ static void cached_dev_detach_finish(struct work_struct *w)
>  		dc->writeback_thread = NULL;
>  	}
>  
> -	memset(&dc->sb.set_uuid, 0, 16);
> -	SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
> -
> -	bch_write_bdev_super(dc, &cl);
> -	closure_sync(&cl);
> -
>  	mutex_lock(&bch_register_lock);
>  
>  	calc_cached_dev_sectors(dc->disk.c);
> diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
> index 4f4ad6b..2cd0340 100644
> --- a/drivers/md/bcache/writeback.c
> +++ b/drivers/md/bcache/writeback.c
> @@ -705,6 +705,15 @@ static int bch_writeback_thread(void *arg)
>  			 * bch_cached_dev_detach().
>  			 */
>  			if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) {
> +				struct closure cl;
> +
> +				closure_init_stack(&cl);
> +				memset(&dc->sb.set_uuid, 0, 16);
> +				SET_BDEV_STATE(&dc->sb, BDEV_STATE_NONE);
> +
> +				bch_write_bdev_super(dc, &cl);
> +				closure_sync(&cl);
> +
>  				up_write(&dc->writeback_lock);
>  				break;
>  			}
> 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux ARM Kernel]     [Linux Filesystem Development]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux