* [PATCH] raid6: fix the input of raid6 algorithm
@ 2016-08-23 3:22 liuzhengyuan
2016-08-23 3:53 ` H. Peter Anvin
0 siblings, 1 reply; 3+ messages in thread
From: liuzhengyuan @ 2016-08-23 3:22 UTC (permalink / raw)
To: hpa
Cc: shli, linux-raid, fenghua.yu, linux-kernel, liuzhengyuang521,
ZhengYuan Liu
From: ZhengYuan Liu <liuzhengyuan@kylinos.cn>
To test and choose an best algorithm for raid6, disk number
and disk data must be offered. Those input depend on page
size and gfmul table at current time. It would lead the disk
number less than 4 when the page size is more than 64KB.This
patch would support arbitrarily page size by defining a macro
for disk number and using random number to fill with disk data.
Signed-off-by: ZhengYuan Liu <liuzhengyuan@kylinos.cn>
---
lib/raid6/algos.c | 36 ++++++++++++++++++++++--------------
1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 975c6e0..f15a4d2 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -23,6 +23,7 @@
#else
#include <linux/module.h>
#include <linux/gfp.h>
+#include <linux/random.h>
#if !RAID6_USE_EMPTY_ZERO_PAGE
/* In .bss so it's zeroed */
const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));
@@ -30,6 +31,8 @@ EXPORT_SYMBOL(raid6_empty_zero_page);
#endif
#endif
+#define RAID6_DISKS 8
+
struct raid6_calls raid6_call;
EXPORT_SYMBOL_GPL(raid6_call);
@@ -129,7 +132,7 @@ static inline const struct raid6_recov_calls *raid6_choose_recov(void)
}
static inline const struct raid6_calls *raid6_choose_gen(
- void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)
+ void *(*const dptrs)[RAID6_DISKS], const int disks)
{
unsigned long perf, bestgenperf, bestxorperf, j0, j1;
int start = (disks>>1)-1, stop = disks-3; /* work on the second half of the disks */
@@ -206,27 +209,32 @@ static inline const struct raid6_calls *raid6_choose_gen(
int __init raid6_select_algo(void)
{
- const int disks = (65536/PAGE_SIZE)+2;
+ const int disks = RAID6_DISKS;
const struct raid6_calls *gen_best;
const struct raid6_recov_calls *rec_best;
- char *syndromes;
- void *dptrs[(65536/PAGE_SIZE)+2];
- int i;
-
- for (i = 0; i < disks-2; i++)
- dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i;
+ char *disk_ptr;
+ void *dptrs[RAID6_DISKS];
+ int i, j;
- /* Normal code - use a 2-page allocation to avoid D$ conflict */
- syndromes = (void *) __get_free_pages(GFP_KERNEL, 1);
+ /* use a 8-page allocation, The first 6 pages for disks
+ and the last 2 pages for syndromes */
+ disk_ptr = (void *) __get_free_pages(GFP_KERNEL, 3);
- if (!syndromes) {
+ if (!disk_ptr) {
pr_err("raid6: Yikes! No memory available.\n");
return -ENOMEM;
}
- dptrs[disks-2] = syndromes;
- dptrs[disks-1] = syndromes + PAGE_SIZE;
+ /* Fix-me: may should use get_random_bytes_arch() instead of get_random_bytes() */
+ for (i = 0; i < disks-2; i++) {
+ dptrs[i] = disk_ptr + PAGE_SIZE*i;
+ for (j = 0; j < PAGE_SIZE; j++)
+ get_random_bytes(dptrs[i]+j, 1);
+ }
+
+ dptrs[disks-2] = disk_ptr + PAGE_SIZE*(disks-2);
+ dptrs[disks-1] = disk_ptr + PAGE_SIZE*(disks-1);
/* select raid gen_syndrome function */
gen_best = raid6_choose_gen(&dptrs, disks);
@@ -234,7 +242,7 @@ int __init raid6_select_algo(void)
/* select raid recover functions */
rec_best = raid6_choose_recov();
- free_pages((unsigned long)syndromes, 1);
+ free_pages((unsigned long)disk_ptr, 3);
return gen_best && rec_best ? 0 : -EINVAL;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] raid6: fix the input of raid6 algorithm
2016-08-23 3:22 [PATCH] raid6: fix the input of raid6 algorithm liuzhengyuan
@ 2016-08-23 3:53 ` H. Peter Anvin
2016-08-24 7:58 ` liuzhengyuan
0 siblings, 1 reply; 3+ messages in thread
From: H. Peter Anvin @ 2016-08-23 3:53 UTC (permalink / raw)
To: liuzhengyuan; +Cc: shli, linux-raid, fenghua.yu, linux-kernel, liuzhengyuang521
On August 22, 2016 8:22:57 PM PDT, liuzhengyuan@kylinos.cn wrote:
>
>To test and choose an best algorithm for raid6, disk number
>and disk data must be offered. Those input depend on page
>size and gfmul table at current time. It would lead the disk
>number less than 4 when the page size is more than 64KB.This
>patch would support arbitrarily page size by defining a macro
>for disk number and using random number to fill with disk data.
>
>Signed-off-by: ZhengYuan Liu <liuzhengyuan@kylinos.cn>
>---
> lib/raid6/algos.c | 36 ++++++++++++++++++++++--------------
> 1 file changed, 22 insertions(+), 14 deletions(-)
>
>diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
>index 975c6e0..f15a4d2 100644
>--- a/lib/raid6/algos.c
>+++ b/lib/raid6/algos.c
>@@ -23,6 +23,7 @@
> #else
> #include <linux/module.h>
> #include <linux/gfp.h>
>+#include <linux/random.h>
> #if !RAID6_USE_EMPTY_ZERO_PAGE
> /* In .bss so it's zeroed */
>const char raid6_empty_zero_page[PAGE_SIZE]
>__attribute__((aligned(256)));
>@@ -30,6 +31,8 @@ EXPORT_SYMBOL(raid6_empty_zero_page);
> #endif
> #endif
>
>+#define RAID6_DISKS 8
>+
> struct raid6_calls raid6_call;
> EXPORT_SYMBOL_GPL(raid6_call);
>
>@@ -129,7 +132,7 @@ static inline const struct raid6_recov_calls
>*raid6_choose_recov(void)
> }
>
> static inline const struct raid6_calls *raid6_choose_gen(
>- void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)
>+ void *(*const dptrs)[RAID6_DISKS], const int disks)
> {
> unsigned long perf, bestgenperf, bestxorperf, j0, j1;
> int start = (disks>>1)-1, stop = disks-3; /* work on the second half
>of the disks */
>@@ -206,27 +209,32 @@ static inline const struct raid6_calls
>*raid6_choose_gen(
>
> int __init raid6_select_algo(void)
> {
>- const int disks = (65536/PAGE_SIZE)+2;
>+ const int disks = RAID6_DISKS;
>
> const struct raid6_calls *gen_best;
> const struct raid6_recov_calls *rec_best;
>- char *syndromes;
>- void *dptrs[(65536/PAGE_SIZE)+2];
>- int i;
>-
>- for (i = 0; i < disks-2; i++)
>- dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i;
>+ char *disk_ptr;
>+ void *dptrs[RAID6_DISKS];
>+ int i, j;
>
>- /* Normal code - use a 2-page allocation to avoid D$ conflict */
>- syndromes = (void *) __get_free_pages(GFP_KERNEL, 1);
>+ /* use a 8-page allocation, The first 6 pages for disks
>+ and the last 2 pages for syndromes */
>+ disk_ptr = (void *) __get_free_pages(GFP_KERNEL, 3);
>
>- if (!syndromes) {
>+ if (!disk_ptr) {
> pr_err("raid6: Yikes! No memory available.\n");
> return -ENOMEM;
> }
>
>- dptrs[disks-2] = syndromes;
>- dptrs[disks-1] = syndromes + PAGE_SIZE;
>+ /* Fix-me: may should use get_random_bytes_arch() instead of
>get_random_bytes() */
>+ for (i = 0; i < disks-2; i++) {
>+ dptrs[i] = disk_ptr + PAGE_SIZE*i;
>+ for (j = 0; j < PAGE_SIZE; j++)
>+ get_random_bytes(dptrs[i]+j, 1);
>+ }
>+
>+ dptrs[disks-2] = disk_ptr + PAGE_SIZE*(disks-2);
>+ dptrs[disks-1] = disk_ptr + PAGE_SIZE*(disks-1);
>
> /* select raid gen_syndrome function */
> gen_best = raid6_choose_gen(&dptrs, disks);
>@@ -234,7 +242,7 @@ int __init raid6_select_algo(void)
> /* select raid recover functions */
> rec_best = raid6_choose_recov();
>
>- free_pages((unsigned long)syndromes, 1);
>+ free_pages((unsigned long)disk_ptr, 3);
>
> return gen_best && rec_best ? 0 : -EINVAL;
> }
Do you have any idea how long this takes to run? People are already complaining about the boot time penalty. get_random_*() is quite expensive and is overkill...
--
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] raid6: fix the input of raid6 algorithm
2016-08-23 3:53 ` H. Peter Anvin
@ 2016-08-24 7:58 ` liuzhengyuan
0 siblings, 0 replies; 3+ messages in thread
From: liuzhengyuan @ 2016-08-24 7:58 UTC (permalink / raw)
To: H. Peter Anvin
Cc: shli, linux-raid, fenghua.yu, linux-kernel, liuzhengyuang521
Oh, get_random_*() is really expensive. Thanks for your tips. The boot log on my aarch64 showed bellow
told it taked about 0.6 second to fill with disk data.
[ 0.172831] DMA: preallocated 256 KiB pool for atomic allocations
[ 0.788664] raid6: int64x1 gen() 121 MB/s
[ 0.856613] raid6: int64x1 xor() 74 MB/s
[ 0.924665] raid6: int64x2 gen() 166 MB/s
[ 0.992846] raid6: int64x2 xor() 95 MB/s
[ 1.060681] raid6: int64x4 gen() 290 MB/s
[ 1.128774] raid6: int64x4 xor() 160 MB/s
[ 1.196933] raid6: int64x8 gen() 238 MB/s
[ 1.264937] raid6: int64x8 xor() 148 MB/s
[ 1.332878] raid6: neonx1 gen() 256 MB/s
[ 1.400975] raid6: neonx1 xor() 130 MB/s
[ 1.468951] raid6: neonx2 gen() 333 MB/s
[ 1.537085] raid6: neonx2 xor() 181 MB/s
[ 1.605042] raid6: neonx4 gen() 451 MB/s
[ 1.673121] raid6: neonx4 xor() 289 MB/s
[ 1.741143] raid6: neonx8 gen() 452 MB/s
[ 1.809151] raid6: neonx8 xor() 277 MB/s
[ 1.809154] raid6: using algorithm neonx8 gen() 452 MB/s
[ 1.809157] raid6: .... xor() 277 MB/s, rmw enabled
[ 1.809160] raid6: using intx1 recovery algorithm
I replaced get_random_* with a local PRNG based on well-know
"linear congruential bit". The patch was like this:
+/* use the linear congruential bit. */
+static int32_t get_random_number_by_lcb(void)
+{
+ static int32_t seed = 1;
+ int32_t ret = 0;
+ ret = ((seed * 1103515245) + 12345) & 0x7fffffff;
+ seed = ret;
+ return ret;
+}
/* Try to pick the best algorithm */
/* This code uses the gfmul table as convenient data set to abuse */
@@ -229,8 +238,8 @@ int __init raid6_select_algo(void)
for (i = 0; i < disks-2; i++) {
dptrs[i] = disk_ptr + PAGE_SIZE*i;
- for (j = 0; j < PAGE_SIZE; j++)
- get_random_bytes(dptrs[i]+j, 1);
+ for (j = 0; j < PAGE_SIZE; j = j + 4)
+ *(int32_t *)(dptrs[i]+j) = get_random_number_by_lcb();
}
dptrs[disks-2] = disk_ptr + PAGE_SIZE*(disks-2);
The boot log with this patch was showd bellow, it taked about 0.08 second.
[ 0.172858] DMA: preallocated 256 KiB pool for atomic allocations
[ 0.256673] raid6: int64x1 gen() 121 MB/s
[ 0.324484] raid6: int64x1 xor() 73 MB/s
[ 0.392606] raid6: int64x2 gen() 166 MB/s
[ 0.460309] raid6: int64x2 xor() 92 MB/s
[ 0.528368] raid6: int64x4 gen() 290 MB/s
[ 0.596401] raid6: int64x4 xor() 156 MB/s
[ 0.664601] raid6: int64x8 gen() 238 MB/s
[ 0.732609] raid6: int64x8 xor() 148 MB/s
[ 0.800523] raid6: neonx1 gen() 256 MB/s
[ 0.868730] raid6: neonx1 xor() 129 MB/s
[ 0.936741] raid6: neonx2 gen() 334 MB/s
[ 1.004717] raid6: neonx2 xor() 202 MB/s
[ 1.072692] raid6: neonx4 gen() 451 MB/s
[ 1.140763] raid6: neonx4 xor() 260 MB/s
[ 1.208842] raid6: neonx8 gen() 452 MB/s
[ 1.276887] raid6: neonx8 xor() 277 MB/s
[ 1.276890] raid6: using algorithm neonx8 gen() 452 MB/s
[ 1.276894] raid6: .... xor() 277 MB/s, rmw enabled
[ 1.276897] raid6: using intx1 recovery algorithm
[ 1.276941] ACPI: Interpreter disabled.
I'm not familiar with spurious D$ conflicts and CPU cache behavior. How do you
think this PRNG or anything else I need to do?
------------------ Original ------------------
From: "H. Peter Anvin"<hpa@zytor.com>;
Date: Tue, Aug 23, 2016 11:53 AM
To: "liuzhengyuan"<liuzhengyuan@kylinos.cn>;
Cc: "shli"<shli@kernel.org>; "linux-raid"<linux-raid@vger.kernel.org>; "fenghua.yu"<fenghua.yu@intel.com>; "linux-kernel"<linux-kernel@vger.kernel.org>; "liuzhengyuang521"<liuzhengyuang521@gmail.com>;
Subject: Re: [PATCH] raid6: fix the input of raid6 algorithm
Do you have any idea how long this takes to run? People are already complaining about the boot time penalty. get_random_*() is quite expensive and is overkill...
--
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-08-24 7:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-23 3:22 [PATCH] raid6: fix the input of raid6 algorithm liuzhengyuan
2016-08-23 3:53 ` H. Peter Anvin
2016-08-24 7:58 ` liuzhengyuan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox