Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jim Kukunas and committed by
NeilBrown
96e67703 2dbf7084

+57 -47
+57 -47
lib/raid6/algos.c
··· 34 34 EXPORT_SYMBOL_GPL(raid6_call); 35 35 36 36 const struct raid6_calls * const raid6_algos[] = { 37 - &raid6_intx1, 38 - &raid6_intx2, 39 - &raid6_intx4, 40 - &raid6_intx8, 41 37 #if defined(__ia64__) 42 38 &raid6_intx16, 43 39 &raid6_intx32, ··· 57 61 &raid6_altivec4, 58 62 &raid6_altivec8, 59 63 #endif 64 + &raid6_intx1, 65 + &raid6_intx2, 66 + &raid6_intx4, 67 + &raid6_intx8, 60 68 NULL 61 69 }; 62 70 ··· 86 86 #define time_before(x, y) ((x) < (y)) 87 87 #endif 88 88 89 - static inline void raid6_choose_recov(void) 89 + static inline const struct raid6_recov_calls *raid6_choose_recov(void) 90 90 { 91 91 const struct raid6_recov_calls *const *algo; 92 92 const struct raid6_recov_calls *best; ··· 103 103 printk("raid6: using %s recovery algorithm\n", best->name); 104 104 } else 105 105 printk("raid6: Yikes! No recovery algorithm found!\n"); 106 + 107 + return best; 106 108 } 107 109 108 - 109 - /* Try to pick the best algorithm */ 110 - /* This code uses the gfmul table as convenient data set to abuse */ 111 - 112 - int __init raid6_select_algo(void) 110 + static inline const struct raid6_calls *raid6_choose_gen( 111 + void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks) 113 112 { 114 - const struct raid6_calls * const * algo; 115 - const struct raid6_calls * best; 116 - char *syndromes; 117 - void *dptrs[(65536/PAGE_SIZE)+2]; 118 - int i, disks; 119 - unsigned long perf, bestperf; 120 - int bestprefer; 121 - unsigned long j0, j1; 113 + unsigned long perf, bestperf, j0, j1; 114 + const struct raid6_calls *const *algo; 115 + const struct raid6_calls *best; 122 116 123 - disks = (65536/PAGE_SIZE)+2; 124 - for ( i = 0 ; i < disks-2 ; i++ ) { 125 - dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; 126 - } 117 + for (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) { 118 + if (!best || (*algo)->prefer >= best->prefer) { 119 + if ((*algo)->valid && !(*algo)->valid()) 120 + continue; 127 121 128 - /* Normal code - use a 2-page allocation to avoid D$ conflict */ 129 - syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); 130 - 131 - if ( !syndromes ) { 132 - printk("raid6: Yikes! No memory available.\n"); 133 - return -ENOMEM; 134 - } 135 - 136 - dptrs[disks-2] = syndromes; 137 - dptrs[disks-1] = syndromes + PAGE_SIZE; 138 - 139 - bestperf = 0; bestprefer = 0; best = NULL; 140 - 141 - for ( algo = raid6_algos ; *algo ; algo++ ) { 142 - if ( !(*algo)->valid || (*algo)->valid() ) { 143 122 perf = 0; 144 123 145 124 preempt_disable(); 146 125 j0 = jiffies; 147 - while ( (j1 = jiffies) == j0 ) 126 + while ((j1 = jiffies) == j0) 148 127 cpu_relax(); 149 128 while (time_before(jiffies, 150 129 j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { 151 - (*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs); 130 + (*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs); 152 131 perf++; 153 132 } 154 133 preempt_enable(); 155 134 156 - if ( (*algo)->prefer > bestprefer || 157 - ((*algo)->prefer == bestprefer && 158 - perf > bestperf) ) { 159 - best = *algo; 160 - bestprefer = best->prefer; 135 + if (perf > bestperf) { 161 136 bestperf = perf; 137 + best = *algo; 162 138 } 163 139 printk("raid6: %-8s %5ld MB/s\n", (*algo)->name, 164 140 (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); ··· 149 173 } else 150 174 printk("raid6: Yikes! No algorithm found!\n"); 151 175 152 - free_pages((unsigned long)syndromes, 1); 176 + return best; 177 + } 178 + 179 + 180 + /* Try to pick the best algorithm */ 181 + /* This code uses the gfmul table as convenient data set to abuse */ 182 + 183 + int __init raid6_select_algo(void) 184 + { 185 + const int disks = (65536/PAGE_SIZE)+2; 186 + 187 + const struct raid6_calls *gen_best; 188 + const struct raid6_recov_calls *rec_best; 189 + char *syndromes; 190 + void *dptrs[(65536/PAGE_SIZE)+2]; 191 + int i; 192 + 193 + for (i = 0; i < disks-2; i++) 194 + dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; 195 + 196 + /* Normal code - use a 2-page allocation to avoid D$ conflict */ 197 + syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); 198 + 199 + if (!syndromes) { 200 + printk("raid6: Yikes! No memory available.\n"); 201 + return -ENOMEM; 202 + } 203 + 204 + dptrs[disks-2] = syndromes; 205 + dptrs[disks-1] = syndromes + PAGE_SIZE; 206 + 207 + /* select raid gen_syndrome function */ 208 + gen_best = raid6_choose_gen(&dptrs, disks); 153 209 154 210 /* select raid recover functions */ 155 - raid6_choose_recov(); 211 + rec_best = raid6_choose_recov(); 156 212 157 - return best ? 0 : -EINVAL; 213 + free_pages((unsigned long)syndromes, 1); 214 + 215 + return gen_best && rec_best ? 0 : -EINVAL; 158 216 } 159 217 160 218 static void raid6_exit(void)