Commit 96e67703e71f4b3cc32b747dbb6158ec74d01e19

Authored by Jim Kukunas
Committed by NeilBrown
1 parent 2dbf708448

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

... ... @@ -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)