diff options
| author | Jim Kukunas <james.t.kukunas@linux.intel.com> | 2012-05-22 13:54:24 +1000 | 
|---|---|---|
| committer | NeilBrown <neilb@suse.de> | 2012-05-22 13:54:24 +1000 | 
| commit | 96e67703e71f4b3cc32b747dbb6158ec74d01e19 (patch) | |
| tree | 7abe4800c1827f5d3b3af42abeb19c8c3ac24df0 /lib/raid6/algos.c | |
| parent | 2dbf708448c836754d25fe6108c5bfe1f5697c95 (diff) | |
| download | olio-linux-3.10-96e67703e71f4b3cc32b747dbb6158ec74d01e19.tar.xz olio-linux-3.10-96e67703e71f4b3cc32b747dbb6158ec74d01e19.zip  | |
lib/raid6: cleanup gen_syndrome function selection
Reorders functions in raid6_algos as well as the preference check
to reduce the number of functions tested on initialization.
Also, creates symmetry between choosing the gen_syndrome functions
and choosing the recovery functions.
Signed-off-by: Jim Kukunas <james.t.kukunas@linux.intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'lib/raid6/algos.c')
| -rw-r--r-- | lib/raid6/algos.c | 104 | 
1 files changed, 57 insertions, 47 deletions
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c index 5a7f8022be1..589f5f50ad2 100644 --- a/lib/raid6/algos.c +++ b/lib/raid6/algos.c @@ -34,10 +34,6 @@ struct raid6_calls raid6_call;  EXPORT_SYMBOL_GPL(raid6_call);  const struct raid6_calls * const raid6_algos[] = { -	&raid6_intx1, -	&raid6_intx2, -	&raid6_intx4, -	&raid6_intx8,  #if defined(__ia64__)  	&raid6_intx16,  	&raid6_intx32, @@ -61,6 +57,10 @@ const struct raid6_calls * const raid6_algos[] = {  	&raid6_altivec4,  	&raid6_altivec8,  #endif +	&raid6_intx1, +	&raid6_intx2, +	&raid6_intx4, +	&raid6_intx8,  	NULL  }; @@ -86,7 +86,7 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {  #define time_before(x, y) ((x) < (y))  #endif -static inline void raid6_choose_recov(void) +static inline const struct raid6_recov_calls *raid6_choose_recov(void)  {  	const struct raid6_recov_calls *const *algo;  	const struct raid6_recov_calls *best; @@ -103,62 +103,38 @@ static inline void raid6_choose_recov(void)  		printk("raid6: using %s recovery algorithm\n", best->name);  	} else  		printk("raid6: Yikes! No recovery algorithm found!\n"); -} - -/* Try to pick the best algorithm */ -/* This code uses the gfmul table as convenient data set to abuse */ +	return best; +} -int __init raid6_select_algo(void) +static inline const struct raid6_calls *raid6_choose_gen( +	void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)  { -	const struct raid6_calls * const * algo; -	const struct raid6_calls * best; -	char *syndromes; -	void *dptrs[(65536/PAGE_SIZE)+2]; -	int i, disks; -	unsigned long perf, bestperf; -	int bestprefer; -	unsigned long j0, j1; - -	disks = (65536/PAGE_SIZE)+2; -	for ( i = 0 ; i < disks-2 ; i++ ) { -		dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; -	} - -	/* Normal code - use a 2-page allocation to avoid D$ conflict */ -	syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); - -	if ( !syndromes ) { -		printk("raid6: Yikes!  No memory available.\n"); -		return -ENOMEM; -	} - -	dptrs[disks-2] = syndromes; -	dptrs[disks-1] = syndromes + PAGE_SIZE; +	unsigned long perf, bestperf, j0, j1; +	const struct raid6_calls *const *algo; +	const struct raid6_calls *best; -	bestperf = 0;  bestprefer = 0;  best = NULL; +	for (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) { +		if (!best || (*algo)->prefer >= best->prefer) { +			if ((*algo)->valid && !(*algo)->valid()) +				continue; -	for ( algo = raid6_algos ; *algo ; algo++ ) { -		if ( !(*algo)->valid || (*algo)->valid() ) {  			perf = 0;  			preempt_disable();  			j0 = jiffies; -			while ( (j1 = jiffies) == j0 ) +			while ((j1 = jiffies) == j0)  				cpu_relax();  			while (time_before(jiffies,  					    j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { -				(*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs); +				(*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs);  				perf++;  			}  			preempt_enable(); -			if ( (*algo)->prefer > bestprefer || -			     ((*algo)->prefer == bestprefer && -			      perf > bestperf) ) { -				best = *algo; -				bestprefer = best->prefer; +			if (perf > bestperf) {  				bestperf = perf; +				best = *algo;  			}  			printk("raid6: %-8s %5ld MB/s\n", (*algo)->name,  			       (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); @@ -173,12 +149,46 @@ int __init raid6_select_algo(void)  	} else  		printk("raid6: Yikes!  No algorithm found!\n"); -	free_pages((unsigned long)syndromes, 1); +	return best; +} + + +/* Try to pick the best algorithm */ +/* This code uses the gfmul table as convenient data set to abuse */ + +int __init raid6_select_algo(void) +{ +	const int disks = (65536/PAGE_SIZE)+2; + +	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; + +	/* Normal code - use a 2-page allocation to avoid D$ conflict */ +	syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); + +	if (!syndromes) { +		printk("raid6: Yikes!  No memory available.\n"); +		return -ENOMEM; +	} + +	dptrs[disks-2] = syndromes; +	dptrs[disks-1] = syndromes + PAGE_SIZE; + +	/* select raid gen_syndrome function */ +	gen_best = raid6_choose_gen(&dptrs, disks);  	/* select raid recover functions */ -	raid6_choose_recov(); +	rec_best = raid6_choose_recov(); + +	free_pages((unsigned long)syndromes, 1); -	return best ? 0 : -EINVAL; +	return gen_best && rec_best ? 0 : -EINVAL;  }  static void raid6_exit(void)  |