diff options
author | Jim Kukunas <james.t.kukunas@linux.intel.com> | 2012-05-21 23:54:24 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 23:54:24 -0400 |
commit | 96e67703e71f4b3cc32b747dbb6158ec74d01e19 (patch) | |
tree | 7abe4800c1827f5d3b3af42abeb19c8c3ac24df0 /lib/raid6 | |
parent | 2dbf708448c836754d25fe6108c5bfe1f5697c95 (diff) |
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')
-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 5a7f8022be13..589f5f50ad2e 100644 --- a/lib/raid6/algos.c +++ b/lib/raid6/algos.c | |||
@@ -34,10 +34,6 @@ struct raid6_calls raid6_call; | |||
34 | EXPORT_SYMBOL_GPL(raid6_call); | 34 | EXPORT_SYMBOL_GPL(raid6_call); |
35 | 35 | ||
36 | const struct raid6_calls * const raid6_algos[] = { | 36 | const struct raid6_calls * const raid6_algos[] = { |
37 | &raid6_intx1, | ||
38 | &raid6_intx2, | ||
39 | &raid6_intx4, | ||
40 | &raid6_intx8, | ||
41 | #if defined(__ia64__) | 37 | #if defined(__ia64__) |
42 | &raid6_intx16, | 38 | &raid6_intx16, |
43 | &raid6_intx32, | 39 | &raid6_intx32, |
@@ -61,6 +57,10 @@ const struct raid6_calls * const raid6_algos[] = { | |||
61 | &raid6_altivec4, | 57 | &raid6_altivec4, |
62 | &raid6_altivec8, | 58 | &raid6_altivec8, |
63 | #endif | 59 | #endif |
60 | &raid6_intx1, | ||
61 | &raid6_intx2, | ||
62 | &raid6_intx4, | ||
63 | &raid6_intx8, | ||
64 | NULL | 64 | NULL |
65 | }; | 65 | }; |
66 | 66 | ||
@@ -86,7 +86,7 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = { | |||
86 | #define time_before(x, y) ((x) < (y)) | 86 | #define time_before(x, y) ((x) < (y)) |
87 | #endif | 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 | const struct raid6_recov_calls *const *algo; | 91 | const struct raid6_recov_calls *const *algo; |
92 | const struct raid6_recov_calls *best; | 92 | const struct raid6_recov_calls *best; |
@@ -103,62 +103,38 @@ static inline void raid6_choose_recov(void) | |||
103 | printk("raid6: using %s recovery algorithm\n", best->name); | 103 | printk("raid6: using %s recovery algorithm\n", best->name); |
104 | } else | 104 | } else |
105 | printk("raid6: Yikes! No recovery algorithm found!\n"); | 105 | printk("raid6: Yikes! No recovery algorithm found!\n"); |
106 | } | ||
107 | |||
108 | 106 | ||
109 | /* Try to pick the best algorithm */ | 107 | return best; |
110 | /* This code uses the gfmul table as convenient data set to abuse */ | 108 | } |
111 | 109 | ||
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; | 113 | unsigned long perf, bestperf, j0, j1; |
115 | const struct raid6_calls * best; | 114 | const struct raid6_calls *const *algo; |
116 | char *syndromes; | 115 | const struct raid6_calls *best; |
117 | void *dptrs[(65536/PAGE_SIZE)+2]; | ||
118 | int i, disks; | ||
119 | unsigned long perf, bestperf; | ||
120 | int bestprefer; | ||
121 | unsigned long j0, j1; | ||
122 | |||
123 | disks = (65536/PAGE_SIZE)+2; | ||
124 | for ( i = 0 ; i < disks-2 ; i++ ) { | ||
125 | dptrs[i] = ((char *)raid6_gfmul) + PAGE_SIZE*i; | ||
126 | } | ||
127 | |||
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 | 116 | ||
139 | bestperf = 0; bestprefer = 0; best = NULL; | 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; | ||
140 | 121 | ||
141 | for ( algo = raid6_algos ; *algo ; algo++ ) { | ||
142 | if ( !(*algo)->valid || (*algo)->valid() ) { | ||
143 | perf = 0; | 122 | perf = 0; |
144 | 123 | ||
145 | preempt_disable(); | 124 | preempt_disable(); |
146 | j0 = jiffies; | 125 | j0 = jiffies; |
147 | while ( (j1 = jiffies) == j0 ) | 126 | while ((j1 = jiffies) == j0) |
148 | cpu_relax(); | 127 | cpu_relax(); |
149 | while (time_before(jiffies, | 128 | while (time_before(jiffies, |
150 | j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { | 129 | j1 + (1<<RAID6_TIME_JIFFIES_LG2))) { |
151 | (*algo)->gen_syndrome(disks, PAGE_SIZE, dptrs); | 130 | (*algo)->gen_syndrome(disks, PAGE_SIZE, *dptrs); |
152 | perf++; | 131 | perf++; |
153 | } | 132 | } |
154 | preempt_enable(); | 133 | preempt_enable(); |
155 | 134 | ||
156 | if ( (*algo)->prefer > bestprefer || | 135 | if (perf > bestperf) { |
157 | ((*algo)->prefer == bestprefer && | ||
158 | perf > bestperf) ) { | ||
159 | best = *algo; | ||
160 | bestprefer = best->prefer; | ||
161 | bestperf = perf; | 136 | bestperf = perf; |
137 | best = *algo; | ||
162 | } | 138 | } |
163 | printk("raid6: %-8s %5ld MB/s\n", (*algo)->name, | 139 | printk("raid6: %-8s %5ld MB/s\n", (*algo)->name, |
164 | (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); | 140 | (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); |
@@ -173,12 +149,46 @@ int __init raid6_select_algo(void) | |||
173 | } else | 149 | } else |
174 | printk("raid6: Yikes! No algorithm found!\n"); | 150 | printk("raid6: Yikes! No algorithm found!\n"); |
175 | 151 | ||
176 | free_pages((unsigned long)syndromes, 1); | 152 | return best; |
153 | } | ||
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); | ||
177 | 185 | ||
178 | /* select raid recover functions */ | 186 | /* select raid recover functions */ |
179 | raid6_choose_recov(); | 187 | rec_best = raid6_choose_recov(); |
188 | |||
189 | free_pages((unsigned long)syndromes, 1); | ||
180 | 190 | ||
181 | return best ? 0 : -EINVAL; | 191 | return gen_best && rec_best ? 0 : -EINVAL; |
182 | } | 192 | } |
183 | 193 | ||
184 | static void raid6_exit(void) | 194 | static void raid6_exit(void) |