diff mbox series

[09/12] badblocks: fix missing bad blocks on retry in _badblocks_check()

Message ID 20250221081109.734170-10-zhengqixing@huaweicloud.com (mailing list archive)
State New
Headers show
Series badblocks: bugfix and cleanup for badblocks | expand

Commit Message

Zheng Qixing Feb. 21, 2025, 8:11 a.m. UTC
From: Zheng Qixing <zhengqixing@huawei.com>

The bad blocks check would miss bad blocks when retrying under contention,
as checking parameters are not reset. These stale values from the previous
attempt could lead to incorrect scanning in the subsequent retry.

Move seqlock to outer function and reinitialize checking state for each
retry. This ensures a clean state for each check attempt, preventing any
missed bad blocks.

Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling")
Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
---
 block/badblocks.c | 50 +++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

Comments

Coly Li Feb. 21, 2025, 10:27 a.m. UTC | #1
On Fri, Feb 21, 2025 at 04:11:06PM +0800, Zheng Qixing wrote:
> From: Zheng Qixing <zhengqixing@huawei.com>
> 
> The bad blocks check would miss bad blocks when retrying under contention,
> as checking parameters are not reset. These stale values from the previous
> attempt could lead to incorrect scanning in the subsequent retry.
> 
> Move seqlock to outer function and reinitialize checking state for each
> retry. This ensures a clean state for each check attempt, preventing any
> missed bad blocks.
> 
> Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling")
> Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>

Looks good to me.

Acked-by: Coly Li <colyli@kernel.org>

Thanks.

> ---
>  block/badblocks.c | 50 +++++++++++++++++++++++------------------------
>  1 file changed, 24 insertions(+), 26 deletions(-)
> 
> diff --git a/block/badblocks.c b/block/badblocks.c
> index 381f9db423d6..79d91be468c4 100644
> --- a/block/badblocks.c
> +++ b/block/badblocks.c
> @@ -1191,31 +1191,12 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
>  static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>  			    sector_t *first_bad, int *bad_sectors)
>  {
> -	int unacked_badblocks, acked_badblocks;
>  	int prev = -1, hint = -1, set = 0;
>  	struct badblocks_context bad;
> -	unsigned int seq;
> +	int unacked_badblocks = 0;
> +	int acked_badblocks = 0;
> +	u64 *p = bb->page;
>  	int len, rv;
> -	u64 *p;
> -
> -	WARN_ON(bb->shift < 0 || sectors == 0);
> -
> -	if (bb->shift > 0) {
> -		sector_t target;
> -
> -		/* round the start down, and the end up */
> -		target = s + sectors;
> -		rounddown(s, 1 << bb->shift);
> -		roundup(target, 1 << bb->shift);
> -		sectors = target - s;
> -	}
> -
> -retry:
> -	seq = read_seqbegin(&bb->lock);
> -
> -	p = bb->page;
> -	unacked_badblocks = 0;
> -	acked_badblocks = 0;
>  
>  re_check:
>  	bad.start = s;
> @@ -1281,9 +1262,6 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>  	else
>  		rv = 0;
>  
> -	if (read_seqretry(&bb->lock, seq))
> -		goto retry;
> -
>  	return rv;
>  }
>  
> @@ -1324,7 +1302,27 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>  int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>  			sector_t *first_bad, int *bad_sectors)
>  {
> -	return _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
> +	unsigned int seq;
> +	int rv;
> +
> +	WARN_ON(bb->shift < 0 || sectors == 0);
> +
> +	if (bb->shift > 0) {
> +		/* round the start down, and the end up */
> +		sector_t target = s + sectors;
> +
> +		rounddown(s, 1 << bb->shift);
> +		roundup(target, 1 << bb->shift);
> +		sectors = target - s;
> +	}
> +
> +retry:
> +	seq = read_seqbegin(&bb->lock);
> +	rv = _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
> +	if (read_seqretry(&bb->lock, seq))
> +		goto retry;
> +
> +	return rv;
>  }
>  EXPORT_SYMBOL_GPL(badblocks_check);
>  
> -- 
> 2.39.2
>
Yu Kuai Feb. 22, 2025, 1:28 a.m. UTC | #2
在 2025/02/21 16:11, Zheng Qixing 写道:
> From: Zheng Qixing <zhengqixing@huawei.com>
> 
> The bad blocks check would miss bad blocks when retrying under contention,
> as checking parameters are not reset. These stale values from the previous
> attempt could lead to incorrect scanning in the subsequent retry.
> 
> Move seqlock to outer function and reinitialize checking state for each
> retry. This ensures a clean state for each check attempt, preventing any
> missed bad blocks.
> 
> Fixes: 3ea3354cb9f0 ("badblocks: improve badblocks_check() for multiple ranges handling")
> Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
> ---
>   block/badblocks.c | 50 +++++++++++++++++++++++------------------------
>   1 file changed, 24 insertions(+), 26 deletions(-)
> 
LGTM
Reviewed-by: Yu Kuai <yukuai3@huawei.com>

> diff --git a/block/badblocks.c b/block/badblocks.c
> index 381f9db423d6..79d91be468c4 100644
> --- a/block/badblocks.c
> +++ b/block/badblocks.c
> @@ -1191,31 +1191,12 @@ static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
>   static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>   			    sector_t *first_bad, int *bad_sectors)
>   {
> -	int unacked_badblocks, acked_badblocks;
>   	int prev = -1, hint = -1, set = 0;
>   	struct badblocks_context bad;
> -	unsigned int seq;
> +	int unacked_badblocks = 0;
> +	int acked_badblocks = 0;
> +	u64 *p = bb->page;
>   	int len, rv;
> -	u64 *p;
> -
> -	WARN_ON(bb->shift < 0 || sectors == 0);
> -
> -	if (bb->shift > 0) {
> -		sector_t target;
> -
> -		/* round the start down, and the end up */
> -		target = s + sectors;
> -		rounddown(s, 1 << bb->shift);
> -		roundup(target, 1 << bb->shift);
> -		sectors = target - s;
> -	}
> -
> -retry:
> -	seq = read_seqbegin(&bb->lock);
> -
> -	p = bb->page;
> -	unacked_badblocks = 0;
> -	acked_badblocks = 0;
>   
>   re_check:
>   	bad.start = s;
> @@ -1281,9 +1262,6 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>   	else
>   		rv = 0;
>   
> -	if (read_seqretry(&bb->lock, seq))
> -		goto retry;
> -
>   	return rv;
>   }
>   
> @@ -1324,7 +1302,27 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>   int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
>   			sector_t *first_bad, int *bad_sectors)
>   {
> -	return _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
> +	unsigned int seq;
> +	int rv;
> +
> +	WARN_ON(bb->shift < 0 || sectors == 0);
> +
> +	if (bb->shift > 0) {
> +		/* round the start down, and the end up */
> +		sector_t target = s + sectors;
> +
> +		rounddown(s, 1 << bb->shift);
> +		roundup(target, 1 << bb->shift);
> +		sectors = target - s;
> +	}
> +
> +retry:
> +	seq = read_seqbegin(&bb->lock);
> +	rv = _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
> +	if (read_seqretry(&bb->lock, seq))
> +		goto retry;
> +
> +	return rv;
>   }
>   EXPORT_SYMBOL_GPL(badblocks_check);
>   
>
diff mbox series

Patch

diff --git a/block/badblocks.c b/block/badblocks.c
index 381f9db423d6..79d91be468c4 100644
--- a/block/badblocks.c
+++ b/block/badblocks.c
@@ -1191,31 +1191,12 @@  static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
 static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
 			    sector_t *first_bad, int *bad_sectors)
 {
-	int unacked_badblocks, acked_badblocks;
 	int prev = -1, hint = -1, set = 0;
 	struct badblocks_context bad;
-	unsigned int seq;
+	int unacked_badblocks = 0;
+	int acked_badblocks = 0;
+	u64 *p = bb->page;
 	int len, rv;
-	u64 *p;
-
-	WARN_ON(bb->shift < 0 || sectors == 0);
-
-	if (bb->shift > 0) {
-		sector_t target;
-
-		/* round the start down, and the end up */
-		target = s + sectors;
-		rounddown(s, 1 << bb->shift);
-		roundup(target, 1 << bb->shift);
-		sectors = target - s;
-	}
-
-retry:
-	seq = read_seqbegin(&bb->lock);
-
-	p = bb->page;
-	unacked_badblocks = 0;
-	acked_badblocks = 0;
 
 re_check:
 	bad.start = s;
@@ -1281,9 +1262,6 @@  static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
 	else
 		rv = 0;
 
-	if (read_seqretry(&bb->lock, seq))
-		goto retry;
-
 	return rv;
 }
 
@@ -1324,7 +1302,27 @@  static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors,
 int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
 			sector_t *first_bad, int *bad_sectors)
 {
-	return _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
+	unsigned int seq;
+	int rv;
+
+	WARN_ON(bb->shift < 0 || sectors == 0);
+
+	if (bb->shift > 0) {
+		/* round the start down, and the end up */
+		sector_t target = s + sectors;
+
+		rounddown(s, 1 << bb->shift);
+		roundup(target, 1 << bb->shift);
+		sectors = target - s;
+	}
+
+retry:
+	seq = read_seqbegin(&bb->lock);
+	rv = _badblocks_check(bb, s, sectors, first_bad, bad_sectors);
+	if (read_seqretry(&bb->lock, seq))
+		goto retry;
+
+	return rv;
 }
 EXPORT_SYMBOL_GPL(badblocks_check);