Commit 96e67703e71f4b3cc32b747dbb6158ec74d01e19
Committed by
NeilBrown
1 parent
2dbf708448
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 57 additions and 47 deletions Side-by-side Diff
lib/raid6/algos.c
| ... | ... | @@ -34,10 +34,6 @@ |
| 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, |
| ... | ... | @@ -61,6 +57,10 @@ |
| 61 | 57 | &raid6_altivec4, |
| 62 | 58 | &raid6_altivec8, |
| 63 | 59 | #endif |
| 60 | + &raid6_intx1, | |
| 61 | + &raid6_intx2, | |
| 62 | + &raid6_intx4, | |
| 63 | + &raid6_intx8, | |
| 64 | 64 | NULL |
| 65 | 65 | }; |
| 66 | 66 | |
| ... | ... | @@ -86,7 +86,7 @@ |
| 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; |
| 93 | 93 | |
| 94 | 94 | |
| 95 | 95 | |
| 96 | 96 | |
| 97 | 97 | |
| 98 | 98 | |
| 99 | 99 | |
| 100 | 100 | |
| ... | ... | @@ -103,62 +103,38 @@ |
| 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)); |
| 165 | 141 | |
| 166 | 142 | |
| 167 | 143 | |
| ... | ... | @@ -173,12 +149,46 @@ |
| 173 | 149 | } else |
| 174 | 150 | printk("raid6: Yikes! No algorithm found!\n"); |
| 175 | 151 | |
| 176 | - free_pages((unsigned long)syndromes, 1); | |
| 152 | + return best; | |
| 153 | +} | |
| 177 | 154 | |
| 155 | + | |
| 156 | +/* Try to pick the best algorithm */ | |
| 157 | +/* This code uses the gfmul table as convenient data set to abuse */ | |
| 158 | + | |
| 159 | +int __init raid6_select_algo(void) | |
| 160 | +{ | |
| 161 | + const int disks = (65536/PAGE_SIZE)+2; | |
| 162 | + | |
| 163 | + const struct raid6_calls *gen_best; | |
| 164 | + const struct raid6_recov_calls *rec_best; | |
| 165 | + char *syndromes; | |
| 166 | + void *dptrs[(65536/PAGE_SIZE)+2]; | |
| 167 | + int i; | |
| 168 | + | |
| 169 | + for (i = 0; i < disks-2; i++) | |
| 170 | + dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; | |
| 171 | + | |
| 172 | + /* Normal code - use a 2-page allocation to avoid D$ conflict */ | |
| 173 | + syndromes = (void *) __get_free_pages(GFP_KERNEL, 1); | |
| 174 | + | |
| 175 | + if (!syndromes) { | |
| 176 | + printk("raid6: Yikes! No memory available.\n"); | |
| 177 | + return -ENOMEM; | |
| 178 | + } | |
| 179 | + | |
| 180 | + dptrs[disks-2] = syndromes; | |
| 181 | + dptrs[disks-1] = syndromes + PAGE_SIZE; | |
| 182 | + | |
| 183 | + /* select raid gen_syndrome function */ | |
| 184 | + gen_best = raid6_choose_gen(&dptrs, disks); | |
| 185 | + | |
| 178 | 186 | /* select raid recover functions */ |
| 179 | - raid6_choose_recov(); | |
| 187 | + rec_best = raid6_choose_recov(); | |
| 180 | 188 | |
| 181 | - return best ? 0 : -EINVAL; | |
| 189 | + free_pages((unsigned long)syndromes, 1); | |
| 190 | + | |
| 191 | + return gen_best && rec_best ? 0 : -EINVAL; | |
| 182 | 192 | } |
| 183 | 193 | |
| 184 | 194 | static void raid6_exit(void) |