mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									2dbf708448
								
							
						
					
					
						commit
						96e67703e7
					
				
					 1 changed files with 57 additions and 47 deletions
				
			
		|  | @ -34,10 +34,6 @@ struct raid6_calls raid6_call; | ||||||
| EXPORT_SYMBOL_GPL(raid6_call); | EXPORT_SYMBOL_GPL(raid6_call); | ||||||
| 
 | 
 | ||||||
| const struct raid6_calls * const raid6_algos[] = { | const struct raid6_calls * const raid6_algos[] = { | ||||||
| 	&raid6_intx1, |  | ||||||
| 	&raid6_intx2, |  | ||||||
| 	&raid6_intx4, |  | ||||||
| 	&raid6_intx8, |  | ||||||
| #if defined(__ia64__) | #if defined(__ia64__) | ||||||
| 	&raid6_intx16, | 	&raid6_intx16, | ||||||
| 	&raid6_intx32, | 	&raid6_intx32, | ||||||
|  | @ -61,6 +57,10 @@ const struct raid6_calls * const raid6_algos[] = { | ||||||
| 	&raid6_altivec4, | 	&raid6_altivec4, | ||||||
| 	&raid6_altivec8, | 	&raid6_altivec8, | ||||||
| #endif | #endif | ||||||
|  | 	&raid6_intx1, | ||||||
|  | 	&raid6_intx2, | ||||||
|  | 	&raid6_intx4, | ||||||
|  | 	&raid6_intx8, | ||||||
| 	NULL | 	NULL | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -86,7 +86,7 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = { | ||||||
| #define time_before(x, y) ((x) < (y)) | #define time_before(x, y) ((x) < (y)) | ||||||
| #endif | #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 *const *algo; | ||||||
| 	const struct raid6_recov_calls *best; | 	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); | 		printk("raid6: using %s recovery algorithm\n", best->name); | ||||||
| 	} else | 	} else | ||||||
| 		printk("raid6: Yikes! No recovery algorithm found!\n"); | 		printk("raid6: Yikes! No recovery algorithm found!\n"); | ||||||
|  | 
 | ||||||
|  | 	return best; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | static inline const struct raid6_calls *raid6_choose_gen( | ||||||
| /* Try to pick the best algorithm */ | 	void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks) | ||||||
| /* This code uses the gfmul table as convenient data set to abuse */ |  | ||||||
| 
 |  | ||||||
| int __init raid6_select_algo(void) |  | ||||||
| { | { | ||||||
| 	const struct raid6_calls * const * algo; | 	unsigned long perf, bestperf, j0, j1; | ||||||
| 	const struct raid6_calls * best; | 	const struct raid6_calls *const *algo; | ||||||
| 	char *syndromes; | 	const struct raid6_calls *best; | ||||||
| 	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 (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) { | ||||||
| 	for ( i = 0 ; i < disks-2 ; i++ ) { | 		if (!best || (*algo)->prefer >= best->prefer) { | ||||||
| 		dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; | 			if ((*algo)->valid && !(*algo)->valid()) | ||||||
| 	} | 				continue; | ||||||
| 
 | 
 | ||||||
| 	/* 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; |  | ||||||
| 
 |  | ||||||
| 	bestperf = 0;  bestprefer = 0;  best = NULL; |  | ||||||
| 
 |  | ||||||
| 	for ( algo = raid6_algos ; *algo ; algo++ ) { |  | ||||||
| 		if ( !(*algo)->valid || (*algo)->valid() ) { |  | ||||||
| 			perf = 0; | 			perf = 0; | ||||||
| 
 | 
 | ||||||
| 			preempt_disable(); | 			preempt_disable(); | ||||||
| 			j0 = jiffies; | 			j0 = jiffies; | ||||||
| 			while ( (j1 = jiffies) == j0 ) | 			while ((j1 = jiffies) == j0) | ||||||
| 				cpu_relax(); | 				cpu_relax(); | ||||||
| 			while (time_before(jiffies, | 			while (time_before(jiffies, | ||||||
| 					    j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { | 					    j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { | ||||||
| 				(*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs); | 				(*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs); | ||||||
| 				perf++; | 				perf++; | ||||||
| 			} | 			} | ||||||
| 			preempt_enable(); | 			preempt_enable(); | ||||||
| 
 | 
 | ||||||
| 			if ( (*algo)->prefer > bestprefer || | 			if (perf > bestperf) { | ||||||
| 			     ((*algo)->prefer == bestprefer && |  | ||||||
| 			      perf > bestperf) ) { |  | ||||||
| 				best = *algo; |  | ||||||
| 				bestprefer = best->prefer; |  | ||||||
| 				bestperf = perf; | 				bestperf = perf; | ||||||
|  | 				best = *algo; | ||||||
| 			} | 			} | ||||||
| 			printk("raid6: %-8s %5ld MB/s\n", (*algo)->name, | 			printk("raid6: %-8s %5ld MB/s\n", (*algo)->name, | ||||||
| 			       (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); | 			       (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); | ||||||
|  | @ -173,12 +149,46 @@ int __init raid6_select_algo(void) | ||||||
| 	} else | 	} else | ||||||
| 		printk("raid6: Yikes!  No algorithm found!\n"); | 		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 */ | 	/* select raid recover functions */ | ||||||
| 	raid6_choose_recov(); | 	rec_best = raid6_choose_recov(); | ||||||
| 
 | 
 | ||||||
| 	return best ? 0 : -EINVAL; | 	free_pages((unsigned long)syndromes, 1); | ||||||
|  | 
 | ||||||
|  | 	return gen_best && rec_best ? 0 : -EINVAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void raid6_exit(void) | static void raid6_exit(void) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Jim Kukunas
						Jim Kukunas