Re: [PATCH] md/raid6: fix algorithm choice under larger PAGE_SIZE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On November 26, 2019 1:16:51 AM PST, Zhengyuan Liu <liuzhengyuan@xxxxxxxxxx> wrote:
>For raid6, we need at least 4 disks to calculate the best algorithm.
>But, currently we assume we are always under 4k PAGE_SIZE, when come
>to larger page size, such as 64K, we may get a wrong xor() and gen().
>
>This patch tries to fix the problem by supporting arbitrarily page
>size.
>
>Signed-off-by: Zhengyuan Liu <liuzhengyuan@xxxxxxxxxx>
>---
> lib/raid6/algos.c | 25 +++++++++++++++----------
> 1 file changed, 15 insertions(+), 10 deletions(-)
>
>diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
>index 17417ee..0df7d99 100644
>--- a/lib/raid6/algos.c
>+++ b/lib/raid6/algos.c
>@@ -118,6 +118,7 @@ const struct raid6_recov_calls *const
>raid6_recov_algos[] = {
> 
> #ifdef __KERNEL__
> #define RAID6_TIME_JIFFIES_LG2	4
>+#define RAID6_DATA_BLOCK_LEN	4096
> #else
> /* Need more time to be stable in userspace */
> #define RAID6_TIME_JIFFIES_LG2	9
>@@ -146,7 +147,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)[(65536/RAID6_DATA_BLOCK_LEN)+2], 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 */
>@@ -171,7 +172,7 @@ static inline const struct raid6_calls
>*raid6_choose_gen(
> 				cpu_relax();
> 			while (time_before(jiffies,
> 					    j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
>-				(*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs);
>+				(*algo)->gen_syndrome(disks, RAID6_DATA_BLOCK_LEN, *dptrs);
> 				perf++;
> 			}
> 			preempt_enable();
>@@ -181,7 +182,8 @@ static inline const struct raid6_calls
>*raid6_choose_gen(
> 				best = *algo;
> 			}
> 			pr_info("raid6: %-8s gen() %5ld MB/s\n", (*algo)->name,
>-			       (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
>+			       (perf*HZ*RAID6_DATA_BLOCK_LEN*(disks-2)) >> \
>+						(20+RAID6_TIME_JIFFIES_LG2));
> 
> 			if (!(*algo)->xor_syndrome)
> 				continue;
>@@ -195,7 +197,7 @@ static inline const struct raid6_calls
>*raid6_choose_gen(
> 			while (time_before(jiffies,
> 					    j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
> 				(*algo)->xor_syndrome(disks, start, stop,
>-						      PAGE_SIZE, *dptrs);
>+						      RAID6_DATA_BLOCK_LEN, *dptrs);
> 				perf++;
> 			}
> 			preempt_enable();
>@@ -204,17 +206,20 @@ static inline const struct raid6_calls
>*raid6_choose_gen(
> 				bestxorperf = perf;
> 
> 			pr_info("raid6: %-8s xor() %5ld MB/s\n", (*algo)->name,
>-				(perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
>+				(perf*HZ*RAID6_DATA_BLOCK_LEN*(disks-2)) >> \
>+						(20+RAID6_TIME_JIFFIES_LG2+1));
> 		}
> 	}
> 
> 	if (best) {
> 		pr_info("raid6: using algorithm %s gen() %ld MB/s\n",
> 		       best->name,
>-		       (bestgenperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
>+		       (bestgenperf*HZ*RAID6_DATA_BLOCK_LEN*(disks-2)) >> \
>+						(20+RAID6_TIME_JIFFIES_LG2));
> 		if (best->xor_syndrome)
> 			pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n",
>-			       (bestxorperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
>+			       (bestxorperf*HZ*RAID6_DATA_BLOCK_LEN*(disks-2)) \
>+						>> (20+RAID6_TIME_JIFFIES_LG2+1));
> 		raid6_call = *best;
> 	} else
> 		pr_err("raid6: Yikes!  No algorithm found!\n");
>@@ -228,16 +233,16 @@ 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 = (65536/RAID6_DATA_BLOCK_LEN)+2;
> 
> 	const struct raid6_calls *gen_best;
> 	const struct raid6_recov_calls *rec_best;
> 	char *syndromes;
>-	void *dptrs[(65536/PAGE_SIZE)+2];
>+	void *dptrs[(65536/RAID6_DATA_BLOCK_LEN)+2];
> 	int i;
> 
> 	for (i = 0; i < disks-2; i++)
>-		dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i;
>+		dptrs[i] = ((char *)raid6_gfmul) + RAID6_DATA_BLOCK_LEN*i;
> 
> 	/* Normal code - use a 2-page allocation to avoid D$ conflict */
> 	syndromes = (void *) __get_free_pages(GFP_KERNEL, 1);

32K, not 4K; it assumes 64K is enough for at least two "disks".

However, as you point out here, there really isn't any particular reason to not just use a 4K chunk for the benchmark; no need to spend a bunch of extra time.
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.




[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux