aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/linear.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/linear.c')
-rw-r--r--drivers/md/linear.c133
1 files changed, 52 insertions, 81 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b9cbee688fae..190147c79e79 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -16,16 +16,8 @@
16 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17*/ 17*/
18 18
19#include <linux/module.h>
20
21#include <linux/raid/md.h>
22#include <linux/slab.h>
23#include <linux/raid/linear.h> 19#include <linux/raid/linear.h>
24 20
25#define MAJOR_NR MD_MAJOR
26#define MD_DRIVER
27#define MD_PERSONALITY
28
29/* 21/*
30 * find which device holds a particular offset 22 * find which device holds a particular offset
31 */ 23 */
@@ -33,16 +25,15 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
33{ 25{
34 dev_info_t *hash; 26 dev_info_t *hash;
35 linear_conf_t *conf = mddev_to_conf(mddev); 27 linear_conf_t *conf = mddev_to_conf(mddev);
36 sector_t block = sector >> 1;
37 28
38 /* 29 /*
39 * sector_div(a,b) returns the remainer and sets a to a/b 30 * sector_div(a,b) returns the remainer and sets a to a/b
40 */ 31 */
41 block >>= conf->preshift; 32 sector >>= conf->sector_shift;
42 (void)sector_div(block, conf->hash_spacing); 33 (void)sector_div(sector, conf->spacing);
43 hash = conf->hash_table[block]; 34 hash = conf->hash_table[sector];
44 35
45 while ((sector>>1) >= (hash->size + hash->offset)) 36 while (sector >= hash->num_sectors + hash->start_sector)
46 hash++; 37 hash++;
47 return hash; 38 return hash;
48} 39}
@@ -65,7 +56,7 @@ static int linear_mergeable_bvec(struct request_queue *q,
65 sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); 56 sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
66 57
67 dev0 = which_dev(mddev, sector); 58 dev0 = which_dev(mddev, sector);
68 maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1)); 59 maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
69 60
70 if (maxsectors < bio_sectors) 61 if (maxsectors < bio_sectors)
71 maxsectors = 0; 62 maxsectors = 0;
@@ -112,8 +103,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
112 dev_info_t **table; 103 dev_info_t **table;
113 mdk_rdev_t *rdev; 104 mdk_rdev_t *rdev;
114 int i, nb_zone, cnt; 105 int i, nb_zone, cnt;
115 sector_t min_spacing; 106 sector_t min_sectors;
116 sector_t curr_offset; 107 sector_t curr_sector;
117 struct list_head *tmp; 108 struct list_head *tmp;
118 109
119 conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), 110 conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
@@ -145,7 +136,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
145 mddev->queue->max_sectors > (PAGE_SIZE>>9)) 136 mddev->queue->max_sectors > (PAGE_SIZE>>9))
146 blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); 137 blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
147 138
148 disk->size = rdev->size; 139 disk->num_sectors = rdev->size * 2;
149 conf->array_sectors += rdev->size * 2; 140 conf->array_sectors += rdev->size * 2;
150 141
151 cnt++; 142 cnt++;
@@ -155,34 +146,34 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
155 goto out; 146 goto out;
156 } 147 }
157 148
158 min_spacing = conf->array_sectors / 2; 149 min_sectors = conf->array_sectors;
159 sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); 150 sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
160 151
161 /* min_spacing is the minimum spacing that will fit the hash 152 /* min_sectors is the minimum spacing that will fit the hash
162 * table in one PAGE. This may be much smaller than needed. 153 * table in one PAGE. This may be much smaller than needed.
163 * We find the smallest non-terminal set of consecutive devices 154 * We find the smallest non-terminal set of consecutive devices
164 * that is larger than min_spacing as use the size of that as 155 * that is larger than min_sectors and use the size of that as
165 * the actual spacing 156 * the actual spacing
166 */ 157 */
167 conf->hash_spacing = conf->array_sectors / 2; 158 conf->spacing = conf->array_sectors;
168 for (i=0; i < cnt-1 ; i++) { 159 for (i=0; i < cnt-1 ; i++) {
169 sector_t sz = 0; 160 sector_t tmp = 0;
170 int j; 161 int j;
171 for (j = i; j < cnt - 1 && sz < min_spacing; j++) 162 for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
172 sz += conf->disks[j].size; 163 tmp += conf->disks[j].num_sectors;
173 if (sz >= min_spacing && sz < conf->hash_spacing) 164 if (tmp >= min_sectors && tmp < conf->spacing)
174 conf->hash_spacing = sz; 165 conf->spacing = tmp;
175 } 166 }
176 167
177 /* hash_spacing may be too large for sector_div to work with, 168 /* spacing may be too large for sector_div to work with,
178 * so we might need to pre-shift 169 * so we might need to pre-shift
179 */ 170 */
180 conf->preshift = 0; 171 conf->sector_shift = 0;
181 if (sizeof(sector_t) > sizeof(u32)) { 172 if (sizeof(sector_t) > sizeof(u32)) {
182 sector_t space = conf->hash_spacing; 173 sector_t space = conf->spacing;
183 while (space > (sector_t)(~(u32)0)) { 174 while (space > (sector_t)(~(u32)0)) {
184 space >>= 1; 175 space >>= 1;
185 conf->preshift++; 176 conf->sector_shift++;
186 } 177 }
187 } 178 }
188 /* 179 /*
@@ -194,9 +185,9 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
194 unsigned round; 185 unsigned round;
195 unsigned long base; 186 unsigned long base;
196 187
197 sz = conf->array_sectors >> (conf->preshift + 1); 188 sz = conf->array_sectors >> conf->sector_shift;
198 sz += 1; /* force round-up */ 189 sz += 1; /* force round-up */
199 base = conf->hash_spacing >> conf->preshift; 190 base = conf->spacing >> conf->sector_shift;
200 round = sector_div(sz, base); 191 round = sector_div(sz, base);
201 nb_zone = sz + (round ? 1 : 0); 192 nb_zone = sz + (round ? 1 : 0);
202 } 193 }
@@ -211,32 +202,31 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
211 * Here we generate the linear hash table 202 * Here we generate the linear hash table
212 * First calculate the device offsets. 203 * First calculate the device offsets.
213 */ 204 */
214 conf->disks[0].offset = 0; 205 conf->disks[0].start_sector = 0;
215 for (i = 1; i < raid_disks; i++) 206 for (i = 1; i < raid_disks; i++)
216 conf->disks[i].offset = 207 conf->disks[i].start_sector =
217 conf->disks[i-1].offset + 208 conf->disks[i-1].start_sector +
218 conf->disks[i-1].size; 209 conf->disks[i-1].num_sectors;
219 210
220 table = conf->hash_table; 211 table = conf->hash_table;
221 curr_offset = 0;
222 i = 0; 212 i = 0;
223 for (curr_offset = 0; 213 for (curr_sector = 0;
224 curr_offset < conf->array_sectors / 2; 214 curr_sector < conf->array_sectors;
225 curr_offset += conf->hash_spacing) { 215 curr_sector += conf->spacing) {
226 216
227 while (i < raid_disks-1 && 217 while (i < raid_disks-1 &&
228 curr_offset >= conf->disks[i+1].offset) 218 curr_sector >= conf->disks[i+1].start_sector)
229 i++; 219 i++;
230 220
231 *table ++ = conf->disks + i; 221 *table ++ = conf->disks + i;
232 } 222 }
233 223
234 if (conf->preshift) { 224 if (conf->sector_shift) {
235 conf->hash_spacing >>= conf->preshift; 225 conf->spacing >>= conf->sector_shift;
236 /* round hash_spacing up so that when we divide by it, 226 /* round spacing up so that when we divide by it,
237 * we err on the side of "too-low", which is safest. 227 * we err on the side of "too-low", which is safest.
238 */ 228 */
239 conf->hash_spacing++; 229 conf->spacing++;
240 } 230 }
241 231
242 BUG_ON(table - conf->hash_table > nb_zone); 232 BUG_ON(table - conf->hash_table > nb_zone);
@@ -317,7 +307,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
317 const int rw = bio_data_dir(bio); 307 const int rw = bio_data_dir(bio);
318 mddev_t *mddev = q->queuedata; 308 mddev_t *mddev = q->queuedata;
319 dev_info_t *tmp_dev; 309 dev_info_t *tmp_dev;
320 sector_t block;
321 int cpu; 310 int cpu;
322 311
323 if (unlikely(bio_barrier(bio))) { 312 if (unlikely(bio_barrier(bio))) {
@@ -332,29 +321,33 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
332 part_stat_unlock(); 321 part_stat_unlock();
333 322
334 tmp_dev = which_dev(mddev, bio->bi_sector); 323 tmp_dev = which_dev(mddev, bio->bi_sector);
335 block = bio->bi_sector >> 1;
336 324
337 if (unlikely(block >= (tmp_dev->size + tmp_dev->offset) 325 if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
338 || block < tmp_dev->offset)) { 326 tmp_dev->start_sector)
327 || (bio->bi_sector <
328 tmp_dev->start_sector))) {
339 char b[BDEVNAME_SIZE]; 329 char b[BDEVNAME_SIZE];
340 330
341 printk("linear_make_request: Block %llu out of bounds on " 331 printk("linear_make_request: Sector %llu out of bounds on "
342 "dev %s size %llu offset %llu\n", 332 "dev %s: %llu sectors, offset %llu\n",
343 (unsigned long long)block, 333 (unsigned long long)bio->bi_sector,
344 bdevname(tmp_dev->rdev->bdev, b), 334 bdevname(tmp_dev->rdev->bdev, b),
345 (unsigned long long)tmp_dev->size, 335 (unsigned long long)tmp_dev->num_sectors,
346 (unsigned long long)tmp_dev->offset); 336 (unsigned long long)tmp_dev->start_sector);
347 bio_io_error(bio); 337 bio_io_error(bio);
348 return 0; 338 return 0;
349 } 339 }
350 if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > 340 if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
351 (tmp_dev->offset + tmp_dev->size)<<1)) { 341 tmp_dev->start_sector + tmp_dev->num_sectors)) {
352 /* This bio crosses a device boundary, so we have to 342 /* This bio crosses a device boundary, so we have to
353 * split it. 343 * split it.
354 */ 344 */
355 struct bio_pair *bp; 345 struct bio_pair *bp;
346
356 bp = bio_split(bio, 347 bp = bio_split(bio,
357 ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector); 348 tmp_dev->start_sector + tmp_dev->num_sectors
349 - bio->bi_sector);
350
358 if (linear_make_request(q, &bp->bio1)) 351 if (linear_make_request(q, &bp->bio1))
359 generic_make_request(&bp->bio1); 352 generic_make_request(&bp->bio1);
360 if (linear_make_request(q, &bp->bio2)) 353 if (linear_make_request(q, &bp->bio2))
@@ -364,7 +357,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
364 } 357 }
365 358
366 bio->bi_bdev = tmp_dev->rdev->bdev; 359 bio->bi_bdev = tmp_dev->rdev->bdev;
367 bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset; 360 bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
361 + tmp_dev->rdev->data_offset;
368 362
369 return 1; 363 return 1;
370} 364}
@@ -372,29 +366,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
372static void linear_status (struct seq_file *seq, mddev_t *mddev) 366static void linear_status (struct seq_file *seq, mddev_t *mddev)
373{ 367{
374 368
375#undef MD_DEBUG
376#ifdef MD_DEBUG
377 int j;
378 linear_conf_t *conf = mddev_to_conf(mddev);
379 sector_t s = 0;
380
381 seq_printf(seq, " ");
382 for (j = 0; j < mddev->raid_disks; j++)
383 {
384 char b[BDEVNAME_SIZE];
385 s += conf->smallest_size;
386 seq_printf(seq, "[%s",
387 bdevname(conf->hash_table[j][0].rdev->bdev,b));
388
389 while (s > conf->hash_table[j][0].offset +
390 conf->hash_table[j][0].size)
391 seq_printf(seq, "/%s] ",
392 bdevname(conf->hash_table[j][1].rdev->bdev,b));
393 else
394 seq_printf(seq, "] ");
395 }
396 seq_printf(seq, "\n");
397#endif
398 seq_printf(seq, " %dk rounding", mddev->chunk_size/1024); 369 seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
399} 370}
400 371