aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/linear.c35
-rw-r--r--include/linux/raid/linear.h6
2 files changed, 21 insertions, 20 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 13e928bde7cd..09a64b9cbde8 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -33,14 +33,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
33{ 33{
34 dev_info_t *hash; 34 dev_info_t *hash;
35 linear_conf_t *conf = mddev_to_conf(mddev); 35 linear_conf_t *conf = mddev_to_conf(mddev);
36 sector_t block = sector >> 1;
37 36
38 /* 37 /*
39 * sector_div(a,b) returns the remainer and sets a to a/b 38 * sector_div(a,b) returns the remainer and sets a to a/b
40 */ 39 */
41 block >>= conf->preshift; 40 sector >>= conf->sector_shift;
42 (void)sector_div(block, conf->hash_spacing); 41 (void)sector_div(sector, conf->spacing);
43 hash = conf->hash_table[block]; 42 hash = conf->hash_table[sector];
44 43
45 while (sector >= hash->num_sectors + hash->start_sector) 44 while (sector >= hash->num_sectors + hash->start_sector)
46 hash++; 45 hash++;
@@ -164,25 +163,25 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
164 * that is larger than min_sectors and use the size of that as 163 * that is larger than min_sectors and use the size of that as
165 * the actual spacing 164 * the actual spacing
166 */ 165 */
167 conf->hash_spacing = conf->array_sectors / 2; 166 conf->spacing = conf->array_sectors;
168 for (i=0; i < cnt-1 ; i++) { 167 for (i=0; i < cnt-1 ; i++) {
169 sector_t tmp = 0; 168 sector_t tmp = 0;
170 int j; 169 int j;
171 for (j = i; j < cnt - 1 && tmp < min_sectors; j++) 170 for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
172 tmp += conf->disks[j].num_sectors; 171 tmp += conf->disks[j].num_sectors;
173 if (tmp >= min_sectors && tmp < conf->hash_spacing * 2) 172 if (tmp >= min_sectors && tmp < conf->spacing)
174 conf->hash_spacing = tmp / 2; 173 conf->spacing = tmp;
175 } 174 }
176 175
177 /* hash_spacing may be too large for sector_div to work with, 176 /* spacing may be too large for sector_div to work with,
178 * so we might need to pre-shift 177 * so we might need to pre-shift
179 */ 178 */
180 conf->preshift = 0; 179 conf->sector_shift = 0;
181 if (sizeof(sector_t) > sizeof(u32)) { 180 if (sizeof(sector_t) > sizeof(u32)) {
182 sector_t space = conf->hash_spacing; 181 sector_t space = conf->spacing;
183 while (space > (sector_t)(~(u32)0)) { 182 while (space > (sector_t)(~(u32)0)) {
184 space >>= 1; 183 space >>= 1;
185 conf->preshift++; 184 conf->sector_shift++;
186 } 185 }
187 } 186 }
188 /* 187 /*
@@ -194,9 +193,9 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
194 unsigned round; 193 unsigned round;
195 unsigned long base; 194 unsigned long base;
196 195
197 sz = conf->array_sectors >> (conf->preshift + 1); 196 sz = conf->array_sectors >> conf->sector_shift;
198 sz += 1; /* force round-up */ 197 sz += 1; /* force round-up */
199 base = conf->hash_spacing >> conf->preshift; 198 base = conf->spacing >> conf->sector_shift;
200 round = sector_div(sz, base); 199 round = sector_div(sz, base);
201 nb_zone = sz + (round ? 1 : 0); 200 nb_zone = sz + (round ? 1 : 0);
202 } 201 }
@@ -221,7 +220,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
221 i = 0; 220 i = 0;
222 for (curr_sector = 0; 221 for (curr_sector = 0;
223 curr_sector < conf->array_sectors; 222 curr_sector < conf->array_sectors;
224 curr_sector += conf->hash_spacing * 2) { 223 curr_sector += conf->spacing) {
225 224
226 while (i < raid_disks-1 && 225 while (i < raid_disks-1 &&
227 curr_sector >= conf->disks[i+1].start_sector) 226 curr_sector >= conf->disks[i+1].start_sector)
@@ -230,12 +229,12 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
230 *table ++ = conf->disks + i; 229 *table ++ = conf->disks + i;
231 } 230 }
232 231
233 if (conf->preshift) { 232 if (conf->sector_shift) {
234 conf->hash_spacing >>= conf->preshift; 233 conf->spacing >>= conf->sector_shift;
235 /* round hash_spacing up so that when we divide by it, 234 /* round spacing up so that when we divide by it,
236 * we err on the side of "too-low", which is safest. 235 * we err on the side of "too-low", which is safest.
237 */ 236 */
238 conf->hash_spacing++; 237 conf->spacing++;
239 } 238 }
240 239
241 BUG_ON(table - conf->hash_table > nb_zone); 240 BUG_ON(table - conf->hash_table > nb_zone);
diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h
index 87090e98529f..f38b9c586afb 100644
--- a/include/linux/raid/linear.h
+++ b/include/linux/raid/linear.h
@@ -15,9 +15,11 @@ struct linear_private_data
15{ 15{
16 struct linear_private_data *prev; /* earlier version */ 16 struct linear_private_data *prev; /* earlier version */
17 dev_info_t **hash_table; 17 dev_info_t **hash_table;
18 sector_t hash_spacing; 18 sector_t spacing;
19 sector_t array_sectors; 19 sector_t array_sectors;
20 int preshift; /* shift before dividing by hash_spacing */ 20 int sector_shift; /* shift before dividing
21 * by spacing
22 */
21 dev_info_t disks[0]; 23 dev_info_t disks[0];
22}; 24};
23 25