diff options
author | Sandeep K Sinha <sandeepksinha@gmail.com> | 2009-06-16 02:55:26 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-06-16 02:55:26 -0400 |
commit | 45d4582f219619e368ea91ea1189085e1c5f1969 (patch) | |
tree | 15c38d1090d67ecb600c395a5155f2630804d851 /drivers/md/linear.c | |
parent | 070ec55d07157a3041f92654135c3c6e2eaaf901 (diff) |
md: Removal of hash table in linear raid
Get rid of sector_div and hash table for linear raid and replace
with a linear search in which_dev.
The hash table adds a lot of complexity for little if any gain.
Ultimately a binary search will be used which will have smaller
cache foot print, a similar number of memory access, and no
divisions.
Signed-off-by: Sandeep K Sinha <sandeepksinha@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/linear.c')
-rw-r--r-- | drivers/md/linear.c | 93 |
1 files changed, 3 insertions, 90 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 31f8ec7131bd..92bcd3dd52cc 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -29,13 +29,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) | |||
29 | { | 29 | { |
30 | dev_info_t *hash; | 30 | dev_info_t *hash; |
31 | linear_conf_t *conf = mddev->private; | 31 | linear_conf_t *conf = mddev->private; |
32 | sector_t idx = sector >> conf->sector_shift; | ||
33 | 32 | ||
34 | /* | 33 | hash = conf->disks; |
35 | * sector_div(a,b) returns the remainer and sets a to a/b | ||
36 | */ | ||
37 | (void)sector_div(idx, conf->spacing); | ||
38 | hash = conf->hash_table[idx]; | ||
39 | 34 | ||
40 | while (sector >= hash->num_sectors + hash->start_sector) | 35 | while (sector >= hash->num_sectors + hash->start_sector) |
41 | hash++; | 36 | hash++; |
@@ -114,11 +109,8 @@ static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
114 | static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | 109 | static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) |
115 | { | 110 | { |
116 | linear_conf_t *conf; | 111 | linear_conf_t *conf; |
117 | dev_info_t **table; | ||
118 | mdk_rdev_t *rdev; | 112 | mdk_rdev_t *rdev; |
119 | int i, nb_zone, cnt; | 113 | int i, cnt; |
120 | sector_t min_sectors; | ||
121 | sector_t curr_sector; | ||
122 | 114 | ||
123 | conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), | 115 | conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), |
124 | GFP_KERNEL); | 116 | GFP_KERNEL); |
@@ -159,63 +151,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
159 | goto out; | 151 | goto out; |
160 | } | 152 | } |
161 | 153 | ||
162 | min_sectors = conf->array_sectors; | ||
163 | sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *)); | ||
164 | if (min_sectors == 0) | ||
165 | min_sectors = 1; | ||
166 | |||
167 | /* min_sectors is the minimum spacing that will fit the hash | ||
168 | * table in one PAGE. This may be much smaller than needed. | ||
169 | * We find the smallest non-terminal set of consecutive devices | ||
170 | * that is larger than min_sectors and use the size of that as | ||
171 | * the actual spacing | ||
172 | */ | ||
173 | conf->spacing = conf->array_sectors; | ||
174 | for (i=0; i < cnt-1 ; i++) { | ||
175 | sector_t tmp = 0; | ||
176 | int j; | ||
177 | for (j = i; j < cnt - 1 && tmp < min_sectors; j++) | ||
178 | tmp += conf->disks[j].num_sectors; | ||
179 | if (tmp >= min_sectors && tmp < conf->spacing) | ||
180 | conf->spacing = tmp; | ||
181 | } | ||
182 | |||
183 | /* spacing may be too large for sector_div to work with, | ||
184 | * so we might need to pre-shift | ||
185 | */ | ||
186 | conf->sector_shift = 0; | ||
187 | if (sizeof(sector_t) > sizeof(u32)) { | ||
188 | sector_t space = conf->spacing; | ||
189 | while (space > (sector_t)(~(u32)0)) { | ||
190 | space >>= 1; | ||
191 | conf->sector_shift++; | ||
192 | } | ||
193 | } | ||
194 | /* | 154 | /* |
195 | * This code was restructured to work around a gcc-2.95.3 internal | 155 | * Here we calculate the device offsets. |
196 | * compiler error. Alter it with care. | ||
197 | */ | ||
198 | { | ||
199 | sector_t sz; | ||
200 | unsigned round; | ||
201 | unsigned long base; | ||
202 | |||
203 | sz = conf->array_sectors >> conf->sector_shift; | ||
204 | sz += 1; /* force round-up */ | ||
205 | base = conf->spacing >> conf->sector_shift; | ||
206 | round = sector_div(sz, base); | ||
207 | nb_zone = sz + (round ? 1 : 0); | ||
208 | } | ||
209 | BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *)); | ||
210 | |||
211 | conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone, | ||
212 | GFP_KERNEL); | ||
213 | if (!conf->hash_table) | ||
214 | goto out; | ||
215 | |||
216 | /* | ||
217 | * Here we generate the linear hash table | ||
218 | * First calculate the device offsets. | ||
219 | */ | 156 | */ |
220 | conf->disks[0].start_sector = 0; | 157 | conf->disks[0].start_sector = 0; |
221 | for (i = 1; i < raid_disks; i++) | 158 | for (i = 1; i < raid_disks; i++) |
@@ -223,29 +160,6 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
223 | conf->disks[i-1].start_sector + | 160 | conf->disks[i-1].start_sector + |
224 | conf->disks[i-1].num_sectors; | 161 | conf->disks[i-1].num_sectors; |
225 | 162 | ||
226 | table = conf->hash_table; | ||
227 | i = 0; | ||
228 | for (curr_sector = 0; | ||
229 | curr_sector < conf->array_sectors; | ||
230 | curr_sector += conf->spacing) { | ||
231 | |||
232 | while (i < raid_disks-1 && | ||
233 | curr_sector >= conf->disks[i+1].start_sector) | ||
234 | i++; | ||
235 | |||
236 | *table ++ = conf->disks + i; | ||
237 | } | ||
238 | |||
239 | if (conf->sector_shift) { | ||
240 | conf->spacing >>= conf->sector_shift; | ||
241 | /* round spacing up so that when we divide by it, | ||
242 | * we err on the side of "too-low", which is safest. | ||
243 | */ | ||
244 | conf->spacing++; | ||
245 | } | ||
246 | |||
247 | BUG_ON(table - conf->hash_table > nb_zone); | ||
248 | |||
249 | return conf; | 163 | return conf; |
250 | 164 | ||
251 | out: | 165 | out: |
@@ -309,7 +223,6 @@ static int linear_stop (mddev_t *mddev) | |||
309 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 223 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
310 | do { | 224 | do { |
311 | linear_conf_t *t = conf->prev; | 225 | linear_conf_t *t = conf->prev; |
312 | kfree(conf->hash_table); | ||
313 | kfree(conf); | 226 | kfree(conf); |
314 | conf = t; | 227 | conf = t; |
315 | } while (conf); | 228 | } while (conf); |