* [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure
@ 2026-02-13 3:14 sunliming
2026-02-13 3:14 ` [PATCH v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: sunliming @ 2026-02-13 3:14 UTC (permalink / raw)
To: song, yukuai; +Cc: linux-raid, linux-kernel, linan666, sunliming
From: sunliming <sunliming@kylinos.cn>
The selection of RAID6 PQ functions involves a dual-strategy approach:
prioritizing startup speed leads to quickly choosing a usable algorithm,
while prioritizing performance leads to selecting an optimal algorithm
via benchmarking. This choice is determined by the RAID6_PQ_BENCHMARK
configuration. This patch series achieves both fast startup and optimal
algorithm selection by initially choosing an algorithm quickly at startup,
then asynchronously determining the optimal algorithm through benchmarking.
Since all RAID6 PQ function algorithms are functionally equivalent despite
performance differences, this approach should be effective.
---
Changes in v3:
Remove the __init annotation from raid6_benchmark_work and benchmark_work_func,
as they are still referenced during initialization.
Changes in v2:
Select the highest-priority algorithm instead of the first one.
Add the cancel_work_sync function in the exit function to handle the
work queue cleanup.
---
sunliming (3):
ib/raid6: Divide the raid6 algorithm selection process into two parts
lib/raid6: Optimizing the raid6_select_algo time through asynchronous
processing
lib/raid6: Delete the RAID6_PQ_BENCHMARK config
include/linux/raid/pq.h | 3 --
lib/Kconfig | 8 ----
lib/raid6/algos.c | 88 ++++++++++++++++++++++++++++++-----------
3 files changed, 65 insertions(+), 34 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts
2026-02-13 3:14 [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
@ 2026-02-13 3:14 ` sunliming
2026-02-13 3:14 ` [PATCH v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: sunliming @ 2026-02-13 3:14 UTC (permalink / raw)
To: song, yukuai; +Cc: linux-raid, linux-kernel, linan666, sunliming
From: sunliming <sunliming@kylinos.cn>
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 <sunliming@kylinos.cn>
---
lib/raid6/algos.c | 76 +++++++++++++++++++++++++++++++++--------------
1 file changed, 54 insertions(+), 22 deletions(-)
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 799e0e5eac26..c21e3ad99d97 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -152,8 +152,32 @@ 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: select the highest priority valid algorithm. */
+static inline int raid6_choose_gen_fast(void)
+{
+ int ret = 0;
+ const struct raid6_calls *const *algo;
+ const struct raid6_calls *best = NULL;
+
+ for (best = NULL, algo = raid6_algos; *algo; algo++)
+ if (!best || (*algo)->priority > best->priority)
+ if (!(*algo)->valid || (*algo)->valid())
+ best = *algo;
+
+ 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");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+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 */
@@ -165,11 +189,6 @@ static inline const struct raid6_calls *raid6_choose_gen(
if ((*algo)->valid && !(*algo)->valid())
continue;
- if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK)) {
- best = *algo;
- break;
- }
-
perf = 0;
preempt_disable();
@@ -200,12 +219,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)) >>
@@ -239,15 +252,13 @@ static inline const struct raid6_calls *raid6_choose_gen(
/* 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(void)
{
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;
+ int i, cycle, ret = 0;
/* prepare the buffer and fill it circularly with gfmul table */
disk_ptr = (char *)__get_free_pages(GFP_KERNEL, RAID6_TEST_DISKS_ORDER);
@@ -269,15 +280,36 @@ 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);
+ if (!gen_best)
+ ret = -EINVAL;
+
+ free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER);
+
+ return ret;
+}
+
+int __init raid6_select_algo(void)
+{
+ int ret = 0;
+ const struct raid6_recov_calls *rec_best = NULL;
+
+ /* select raid gen_syndrome functions */
+ if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK))
+ ret = raid6_choose_gen_fast();
+ else
+ ret = raid6_choose_gen_benmark();
+
+ if (ret < 0)
+ goto out;
/* select raid recover functions */
rec_best = raid6_choose_recov();
+ if (!rec_best)
+ ret = -EINVAL;
- free_pages((unsigned long)disk_ptr, RAID6_TEST_DISKS_ORDER);
-
- return gen_best && rec_best ? 0 : -EINVAL;
+out:
+ return ret;
}
static void raid6_exit(void)
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing
2026-02-13 3:14 [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
2026-02-13 3:14 ` [PATCH v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
@ 2026-02-13 3:14 ` sunliming
2026-02-13 3:14 ` [PATCH v3 3/3] lib/raid6: Delete the RAID6_PQ_BENCHMARK config sunliming
2026-02-13 8:15 ` [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: sunliming @ 2026-02-13 3:14 UTC (permalink / raw)
To: song, yukuai; +Cc: linux-raid, linux-kernel, linan666, sunliming
From: sunliming <sunliming@kylinos.cn>
Optimizing the raid6_select_algo time. In raid6_select_algo(), an raid6 gen
algorithm is first selected quickly through synchronous processing, while
the time-consuming process of selecting the optimal algorithm via benchmarking
is handled asynchronously. This approach speeds up the overall startup time
and ultimately ensures the selection of an optimal algorithm.
Signed-off-by: sunliming <sunliming@kylinos.cn>
---
lib/raid6/algos.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index c21e3ad99d97..b8b5515ac7a6 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -12,6 +12,7 @@
*/
#include <linux/raid/pq.h>
+#include <linux/workqueue.h>
#ifndef __KERNEL__
#include <sys/mman.h>
#include <stdio.h>
@@ -166,7 +167,7 @@ static inline int raid6_choose_gen_fast(void)
if (best) {
raid6_call = *best;
- pr_info("raid6: skipped pq benchmark and selected %s\n",
+ pr_info("raid6: raid6: fast selected %s, async benchmark pending\n",
best->name);
} else {
pr_err("raid6: No valid algorithm found even for fast selection!\n");
@@ -213,7 +214,7 @@ static inline const struct raid6_calls *raid6_gen_benchmark(
}
if (!best) {
- pr_err("raid6: Yikes! No algorithm found!\n");
+ pr_warn("raid6: async benchmark failed to find any algorithm\n");
goto out;
}
@@ -289,24 +290,33 @@ static int raid6_choose_gen_benmark(void)
return ret;
}
+static struct work_struct raid6_benchmark_work;
+
+static void benchmark_work_func(struct work_struct *work)
+{
+ raid6_choose_gen_benmark();
+}
+
int __init raid6_select_algo(void)
{
int ret = 0;
const struct raid6_recov_calls *rec_best = NULL;
- /* select raid gen_syndrome functions */
- if (!IS_ENABLED(CONFIG_RAID6_PQ_BENCHMARK))
- ret = raid6_choose_gen_fast();
- else
- ret = raid6_choose_gen_benmark();
-
+ /* phase 1: synchronous fast selection generation algorithm */
+ ret = raid6_choose_gen_fast();
if (ret < 0)
goto out;
/* select raid recover functions */
rec_best = raid6_choose_recov();
- if (!rec_best)
+ if (!rec_best) {
ret = -EINVAL;
+ goto out;
+ }
+
+ /* phase 2: asynchronous performance benchmarking */
+ INIT_WORK(&raid6_benchmark_work, benchmark_work_func);
+ schedule_work(&raid6_benchmark_work);
out:
return ret;
@@ -314,7 +324,7 @@ int __init raid6_select_algo(void)
static void raid6_exit(void)
{
- do { } while (0);
+ cancel_work_sync(&raid6_benchmark_work);
}
subsys_initcall(raid6_select_algo);
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v3 3/3] lib/raid6: Delete the RAID6_PQ_BENCHMARK config
2026-02-13 3:14 [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
2026-02-13 3:14 ` [PATCH v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
2026-02-13 3:14 ` [PATCH v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
@ 2026-02-13 3:14 ` sunliming
2026-02-13 8:15 ` [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: sunliming @ 2026-02-13 3:14 UTC (permalink / raw)
To: song, yukuai; +Cc: linux-raid, linux-kernel, linan666, sunliming
From: sunliming <sunliming@kylinos.cn>
Now RAID6 PQ functions is automatically choosed and the
RAID6_PQ_BENCHMARK is not needed.
Signed-off-by: sunliming <sunliming@kylinos.cn>
---
include/linux/raid/pq.h | 3 ---
lib/Kconfig | 8 --------
2 files changed, 11 deletions(-)
diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
index 2467b3be15c9..6378ec4ae4ba 100644
--- a/include/linux/raid/pq.h
+++ b/include/linux/raid/pq.h
@@ -67,9 +67,6 @@ extern const char raid6_empty_zero_page[PAGE_SIZE];
#define MODULE_DESCRIPTION(desc)
#define subsys_initcall(x)
#define module_exit(x)
-
-#define IS_ENABLED(x) (x)
-#define CONFIG_RAID6_PQ_BENCHMARK 1
#endif /* __KERNEL__ */
/* Routine choices */
diff --git a/lib/Kconfig b/lib/Kconfig
index 2923924bea78..841a0245a2c4 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -11,14 +11,6 @@ menu "Library routines"
config RAID6_PQ
tristate
-config RAID6_PQ_BENCHMARK
- bool "Automatically choose fastest RAID6 PQ functions"
- depends on RAID6_PQ
- default y
- help
- Benchmark all available RAID6 PQ functions on init and choose the
- fastest one.
-
config LINEAR_RANGES
tristate
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure
2026-02-13 3:14 [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
` (2 preceding siblings ...)
2026-02-13 3:14 ` [PATCH v3 3/3] lib/raid6: Delete the RAID6_PQ_BENCHMARK config sunliming
@ 2026-02-13 8:15 ` Christoph Hellwig
3 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2026-02-13 8:15 UTC (permalink / raw)
To: sunliming; +Cc: song, yukuai, linux-raid, linux-kernel, linan666, sunliming
This is actually a very bad idea.
The current indirect calls for the raid parity generation are very
expensive and need to be replaced by static calls. Doing runtime
switching defeats this.
I had started on doing the static calls a while ago, let me try to
finish that off.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-02-13 8:15 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-13 3:14 [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
2026-02-13 3:14 ` [PATCH v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
2026-02-13 3:14 ` [PATCH v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
2026-02-13 3:14 ` [PATCH v3 3/3] lib/raid6: Delete the RAID6_PQ_BENCHMARK config sunliming
2026-02-13 8:15 ` [PATCH v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox