157 lines
4.3 KiB
Diff
157 lines
4.3 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||
|
Date: Fri, 27 May 2016 09:26:51 -0400
|
||
|
Subject: [PATCH] raid6: add Kconfig option to skip raid6 benchmarking
|
||
|
|
||
|
Adds CONFIG_RAID6_FORCE_ALGO, which causes the kernel to not benchmark
|
||
|
each raid recovery and syndrome generation algorithm, and instead use
|
||
|
the version selected via Kconfig (CONFIG_RAID6_FORCE_{INT,SSSE3,AVX2}).
|
||
|
In the case, the selected algorithm is not supported by the processor at
|
||
|
runtime, a fallback is used.
|
||
|
|
||
|
Signed-off-by: Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||
|
---
|
||
|
lib/Kconfig | 3 +--
|
||
|
lib/raid6/Kconfig | 38 +++++++++++++++++++++++++++++++
|
||
|
lib/raid6/algos.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
3 files changed, 97 insertions(+), 2 deletions(-)
|
||
|
create mode 100644 lib/raid6/Kconfig
|
||
|
|
||
|
diff --git a/lib/Kconfig b/lib/Kconfig
|
||
|
index 3321d04dfa5a..e4343fa05964 100644
|
||
|
--- a/lib/Kconfig
|
||
|
+++ b/lib/Kconfig
|
||
|
@@ -8,8 +8,7 @@ config BINARY_PRINTF
|
||
|
|
||
|
menu "Library routines"
|
||
|
|
||
|
-config RAID6_PQ
|
||
|
- tristate
|
||
|
+source "lib/raid6/Kconfig"
|
||
|
|
||
|
config RAID6_PQ_BENCHMARK
|
||
|
bool "Automatically choose fastest RAID6 PQ functions"
|
||
|
diff --git a/lib/raid6/Kconfig b/lib/raid6/Kconfig
|
||
|
new file mode 100644
|
||
|
index 000000000000..d881d6be89bb
|
||
|
--- /dev/null
|
||
|
+++ b/lib/raid6/Kconfig
|
||
|
@@ -0,0 +1,38 @@
|
||
|
+menu "RAID 6"
|
||
|
+
|
||
|
+config RAID6_PQ
|
||
|
+ tristate
|
||
|
+
|
||
|
+config RAID6_FORCE_ALGO
|
||
|
+ bool "Always use specified recovery algorithm"
|
||
|
+ default n
|
||
|
+ depends on RAID6_PQ
|
||
|
+ help
|
||
|
+ If this option is not set, on every boot the kernel will
|
||
|
+ benchmark each optimized version of the RAID6 recovery and
|
||
|
+ syndrome generation algorithms and will select the one that
|
||
|
+ performs best. Microbenchmarking each version negatively
|
||
|
+ affects boot time.
|
||
|
+
|
||
|
+ Enabling this option skips the benchmark at boot, and
|
||
|
+ instead always uses the algorithm selected. The only exception
|
||
|
+ is if the selected algorithm relies on a cpu feature not
|
||
|
+ supported at runtime. In this case, one of the lower performance
|
||
|
+ fallbacks are used.
|
||
|
+
|
||
|
+choice
|
||
|
+ prompt "RAID6 Recovery Algorithm"
|
||
|
+ default RAID6_FORCE_INT
|
||
|
+ depends on RAID6_FORCE_ALGO
|
||
|
+ ---help---
|
||
|
+ Select the RAID6 recovery algorithm to unconditionally use
|
||
|
+
|
||
|
+ config RAID6_FORCE_INT
|
||
|
+ bool "Reference Implementation"
|
||
|
+ config RAID6_FORCE_SSSE3
|
||
|
+ bool "SSSE3"
|
||
|
+ config RAID6_FORCE_AVX2
|
||
|
+ bool "AVX2"
|
||
|
+endchoice
|
||
|
+
|
||
|
+endmenu
|
||
|
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
|
||
|
index 17417eee0866..8af3d7c737c1 100644
|
||
|
--- a/lib/raid6/algos.c
|
||
|
+++ b/lib/raid6/algos.c
|
||
|
@@ -124,6 +124,63 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {
|
||
|
#define time_before(x, y) ((x) < (y))
|
||
|
#endif
|
||
|
|
||
|
+#ifdef CONFIG_RAID6_FORCE_ALGO
|
||
|
+/* TODO don't compile in algos that will never be used */
|
||
|
+int __init raid6_select_algo(void)
|
||
|
+{
|
||
|
+ const struct raid6_recov_calls *recov_fallback = &raid6_recov_intx1;
|
||
|
+ const struct raid6_recov_calls *recov_algo;
|
||
|
+ const struct raid6_calls *gen_fallback;
|
||
|
+ const struct raid6_calls *gen_algo;
|
||
|
+
|
||
|
+#if defined(__i386__)
|
||
|
+ gen_fallback = &raid6_intx32;
|
||
|
+#elif defined(__x86_64__)
|
||
|
+ gen_fallback = &raid6_sse2x2;
|
||
|
+#else
|
||
|
+# error "TODO"
|
||
|
+#endif
|
||
|
+
|
||
|
+#if defined(CONFIG_RAID6_FORCE_INT)
|
||
|
+ recov_algo = &raid6_recov_intx1;
|
||
|
+ gen_algo = &raid6_intx32;
|
||
|
+
|
||
|
+#elif defined(CONFIG_RAID6_FORCE_SSSE3)
|
||
|
+ recov_algo = &raid6_recov_ssse3;
|
||
|
+#if defined(__i386__)
|
||
|
+ gen_algo = &raid6_sse2x2;
|
||
|
+#else
|
||
|
+ gen_algo = &raid6_sse2x4;
|
||
|
+#endif
|
||
|
+
|
||
|
+#elif defined(CONFIG_RAID6_FORCE_AVX2)
|
||
|
+ recov_algo = &raid6_recov_avx2;
|
||
|
+
|
||
|
+#if defined(__i386__)
|
||
|
+ gen_algo = &raid6_avx2x2;
|
||
|
+#else
|
||
|
+ gen_algo = &raid6_avx2x4;
|
||
|
+#endif
|
||
|
+
|
||
|
+#else
|
||
|
+#error "RAID6 Forced Recov Algo: Unsupported selection"
|
||
|
+#endif
|
||
|
+
|
||
|
+ if (recov_algo->valid != NULL && recov_algo->valid() == 0)
|
||
|
+ recov_algo = recov_fallback;
|
||
|
+
|
||
|
+ pr_info("raid6: Forced to use recovery algorithm %s\n", recov_algo->name);
|
||
|
+
|
||
|
+ raid6_2data_recov = recov_algo->data2;
|
||
|
+ raid6_datap_recov = recov_algo->datap;
|
||
|
+
|
||
|
+ pr_info("raid6: Forced gen() algo %s\n", gen_algo->name);
|
||
|
+
|
||
|
+ raid6_call = *gen_algo;
|
||
|
+
|
||
|
+ return gen_algo && recov_algo ? 0 : -EINVAL;
|
||
|
+}
|
||
|
+#else
|
||
|
static inline const struct raid6_recov_calls *raid6_choose_recov(void)
|
||
|
{
|
||
|
const struct raid6_recov_calls *const *algo;
|
||
|
@@ -260,6 +317,7 @@ int __init raid6_select_algo(void)
|
||
|
|
||
|
return gen_best && rec_best ? 0 : -EINVAL;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static void raid6_exit(void)
|
||
|
{
|
||
|
--
|
||
|
https://clearlinux.org
|
||
|
|