Re: [PATCH 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts

Li Nan <[email protected]>
Newsgroups gmane.linux.raid,gmane.linux.kernel
Message-ID <[email protected]>

在 2026/1/28 18:49, [email protected] 写道:
> From: sunliming <[email protected]>
> 
> Divide the RAID6 algorithm selection process into two parts: fast selection
> and benchmark selection. To prepare for the asynchronous processing of
> the benchmark phase.
> 
> Signed-off-by: sunliming <[email protected]>
> ---
>   lib/raid6/algos.c | 76 +++++++++++++++++++++++++++++++----------------
>   1 file changed, 51 insertions(+), 25 deletions(-)
> 
> diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
> index 799e0e5eac26..ac6a77b0ae1d 100644
> --- a/lib/raid6/algos.c
> +++ b/lib/raid6/algos.c
> @@ -134,7 +134,7 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {
>   static inline const struct raid6_recov_calls *raid6_choose_recov(void)
>   {
>   	const struct raid6_recov_calls *const *algo;
> -	const struct raid6_recov_calls *best;
> +	const struct raid6_recov_calls *best = NULL;
>   
>   	for (best = NULL, algo = raid6_recov_algos; *algo; algo++)
>   		if (!best || (*algo)->priority > best->priority)
> @@ -152,24 +152,44 @@ static inline const struct raid6_recov_calls *raid6_choose_recov(void)
>   	return best;
>   }
>   
> -static inline const struct raid6_calls *raid6_choose_gen(
> -	void *(*const dptrs)[RAID6_TEST_DISKS], const int disks)
> +/* Quick selection: selects the first valid algorithm. */
> +static inline const struct raid6_calls *raid6_choose_gen_fast(void)
> +{
> +	const struct raid6_calls *const *algo;
> +	const struct raid6_calls *best = NULL;
> +
> +	for (algo = raid6_algos; *algo; algo++) {
> +		if ((*algo)->valid && !(*algo)->valid())
> +			continue;
This logic is odd. We should select the highest-priority algorithm
instead of the first one. This was introduced by commit be85f93ae2df
("lib/raid6: add option to skip algorithm benchmarking").

After fix, this logic is identical to raid6_choose_recov(). Could we reuse
it after renaming the function?


> +
> +		best = *algo;
> +		break;
> +	}
> +
> +	if (best) {
> +		raid6_call = *best;
> +		pr_info("raid6: skipped pq benchmark and selected %s\n",
> +			best->name);
> +	} else {
> +		pr_err("raid6: No valid algorithm found even for fast selection!\n");
> +	}
> +
> +	return best;
> +}
> +
> +static inline const struct raid6_calls *raid6_gen_benchmark(
> +		void *(*const dptrs)[RAID6_TEST_DISKS], const int disks)
>   {
>   	unsigned long perf, bestgenperf, j0, j1;
>   	int start = (disks>>1)-1, stop = disks-3;	/* work on the second half of the disks */
>   	const struct raid6_calls *const *algo;
> -	const struct raid6_calls *best;
> +	const struct raid6_calls *best = NULL;
>   
>   	for (bestgenperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
>   		if (!best || (*algo)->priority >= best->priority) {
>   			if ((*algo)->valid && !(*algo)->valid())
>   				continue;
>   
> -			if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) {
> -				best = *algo;
> -				break;
> -			}
> -
>   			perf = 0;
>   
>   			preempt_disable();
> @@ -200,12 +220,6 @@ static inline const struct raid6_calls *raid6_choose_gen(
>   
>   	raid6_call = *best;
>   
> -	if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) {
> -		pr_info("raid6: skipped pq benchmark and selected %s\n",
> -			best->name);
> -		goto out;
> -	}
> -
>   	pr_info("raid6: using algorithm %s gen() %ld MB/s\n",
>   		best->name,
>   		(bestgenperf * HZ * (disks - 2)) >>
> @@ -235,16 +249,11 @@ static inline const struct raid6_calls *raid6_choose_gen(
>   	return best;
>   }
>   
> -
>   /* Try to pick the best algorithm */
>   /* This code uses the gfmul table as convenient data set to abuse */
> -
> -int __init raid6_select_algo(void)
> +static int raid6_choose_gen_benmark(const struct raid6_calls **gen_best)
>   {
>   	const int disks = RAID6_TEST_DISKS;
> -
> -	const struct raid6_calls *gen_best;
> -	const struct raid6_recov_calls *rec_best;
>   	char *disk_ptr, *p;
>   	void *dptrs[RAID6_TEST_DISKS];
>   	int i, cycle;
> @@ -269,14 +278,31 @@ int __init raid6_select_algo(void)
>   	if ((disks - 2) * PAGE_SIZE % 65536)
>   		memcpy(p, raid6_gfmul, (disks - 2) * PAGE_SIZE % 65536);
>   
> -	/* select raid gen_syndrome function */
> -	gen_best = raid6_choose_gen(&dptrs, disks);
> +	*gen_best = raid6_gen_benchmark(&dptrs, disks);
> +
> +	free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER);
> +
> +	return 0;
> +}
> +
> +int __init raid6_select_algo(void)
> +{
> +	int ret;
> +	const struct raid6_calls *gen_best = NULL;
> +	const struct raid6_recov_calls *rec_best = NULL;
> +
> +	/* select raid gen_syndrome functions */
> +	if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK))
> +		gen_best = raid6_choose_gen_fast();
> +	else {
> +		ret = raid6_choose_gen_benmark(&gen_best);

'gen_best' is meaningless, use 'ret' directly. The input parameter of 
raid6_choose_gen_benchmark() can be modified to void.

> +		if (ret < 0)
> +			return ret;
> +	}
>   
>   	/* select raid recover functions */
>   	rec_best = raid6_choose_recov();
>   
> -	free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER);
> -
>   	return gen_best && rec_best ? 0 : -EINVAL;
>   }
>   

-- 
Thanks,
Nan
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.