* [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure
@ 2026-03-20 6:00 sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
0 siblings, 2 replies; 4+ messages in thread
From: sunliming @ 2026-03-20 6:00 UTC (permalink / raw)
To: song, yukuai, akpm; +Cc: linux-raid, linux-kernel, 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] 4+ messages in thread
* [PATCH RESEND v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts
2026-03-20 6:00 [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
@ 2026-03-20 6:00 ` sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
1 sibling, 0 replies; 4+ messages in thread
From: sunliming @ 2026-03-20 6:00 UTC (permalink / raw)
To: song, yukuai, akpm; +Cc: linux-raid, linux-kernel, 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] 4+ messages in thread
* [PATCH RESEND v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing
2026-03-20 6:00 [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
@ 2026-03-20 6:00 ` sunliming
1 sibling, 0 replies; 4+ messages in thread
From: sunliming @ 2026-03-20 6:00 UTC (permalink / raw)
To: song, yukuai, akpm; +Cc: linux-raid, linux-kernel, 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] 4+ messages in thread
* [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure
@ 2026-03-20 6:07 sunliming
0 siblings, 0 replies; 4+ messages in thread
From: sunliming @ 2026-03-20 6:07 UTC (permalink / raw)
To: song, yukuai, akpm; +Cc: linux-raid, linux-kernel, 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] 4+ messages in thread
end of thread, other threads:[~2026-03-20 6:08 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-20 6:00 [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 1/3] lib/raid6: Divide the raid6 algorithm selection process into two parts sunliming
2026-03-20 6:00 ` [PATCH RESEND v3 2/3] lib/raid6: Optimizing the raid6_select_algo time through asynchronous processing sunliming
-- strict thread matches above, loose matches on Subject: below --
2026-03-20 6:07 [PATCH RESEND v3 0/3] lib/raid6: Optimize raid6_select_algo to ensure sunliming
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox