Re: [PATCH 12/12] btrfs: add correction to handle -1 edge case in async discard

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

 




On 2.01.20 г. 23:26 ч., Dennis Zhou wrote:
> From Dave's testing, it's possible to drive a file system to have -1
> discardable_extents and a corresponding negative discardable_bytes. As
> btrfs_discard_calc_delay() is the only user of discardable_extents, we
> can correct here for any negative discardable_extents/discardable_bytes.
> 
> Reported-by: David Sterba <dsterba@xxxxxxxx>
> Signed-off-by: Dennis Zhou <dennis@xxxxxxxxxx>
> ---
>  fs/btrfs/discard.c | 24 +++++++++++++++++++++---
>  1 file changed, 21 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c
> index d5a89e3755ed..d2c7851e31de 100644
> --- a/fs/btrfs/discard.c
> +++ b/fs/btrfs/discard.c
> @@ -518,14 +518,32 @@ void btrfs_discard_calc_delay(struct btrfs_discard_ctl *discard_ctl)
>  {
>  	s32 discardable_extents =
>  		atomic_read(&discard_ctl->discardable_extents);
> +	s64 discardable_bytes = atomic64_read(&discard_ctl->discardable_bytes);
>  	unsigned iops_limit;
>  	unsigned long delay, lower_limit = BTRFS_DISCARD_MIN_DELAY_MSEC;
>  
> -	if (!discardable_extents)
> -		return;
> -
>  	spin_lock(&discard_ctl->lock);
>  
> +	/*
> +	 * The following is to fix a potential -1 discrepenancy that I'm not
> +	 * sure how to reproduce.  But given that this is the only place that
> +	 * utilizes these numbers and this is only called by from
> +	 * btrfs_finish_extent_commit() which is synchronized, we can correct
> +	 * here.
> +	 */
> +	if (discardable_extents < 0)
> +		atomic_add(-discardable_extents,
> +			   &discard_ctl->discardable_extents);
> +
> +	if (discardable_bytes < 0)
> +		atomic64_add(-discardable_bytes,
> +			     &discard_ctl->discardable_bytes);
> +
> +	if (discardable_extents <= 0) {
> +		spin_unlock(&discard_ctl->lock);
> +		return;
> +	}

Perhaps a WARN_ON for each of those conditions? AFAIU this is papering
over a real issue which is still not fully diagnosed, no? In this case
if someone hits it in the wild they could come back with some stack traces?

> +
>  	iops_limit = READ_ONCE(discard_ctl->iops_limit);
>  	if (iops_limit)
>  		lower_limit = max_t(unsigned long, lower_limit,
> 



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux