aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Noll <maan@systemlinux.org>2009-06-16 02:18:43 -0400
committerNeilBrown <neilb@suse.de>2009-06-16 02:18:43 -0400
commitdc58266385e51420298275c90a616c34f1473a73 (patch)
treef7532a7886f71c0b4e863033e95f8b57fb1ca1f2
parent45e3e1935e2857c54783291107d33323b3ef33c8 (diff)
md: raid0: Replace hash table lookup by looping over all strip_zones.
The number of strip_zones of a raid0 array is bounded by the number of drives in the array and is in fact much smaller for typical setups. For example, any raid0 array containing identical disks will have only a single strip_zone. Therefore, the hash tables which are used for quickly finding the strip_zone that holds a particular sector are of questionable value and add quite a bit of unnecessary complexity. This patch replaces the hash table lookup by equivalent code which simply loops over all strip zones to find the zone that holds the given sector. In order to make this loop as fast as possible, the zone->start field of struct strip_zone has been renamed to zone_end, and it now stores the beginning of the next zone in sectors. This allows to save one addition in the loop. Subsequent cleanup patches will remove the hash table structure. Signed-off-by: Andre Noll <maan@systemlinux.org> Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/raid0.c40
-rw-r--r--drivers/md/raid0.h2
2 files changed, 21 insertions, 21 deletions
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 925507e7d673..bb245a6d16c8 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -52,7 +52,6 @@ static int raid0_congested(void *data, int bits)
52 return ret; 52 return ret;
53} 53}
54 54
55
56static int create_strip_zones (mddev_t *mddev) 55static int create_strip_zones (mddev_t *mddev)
57{ 56{
58 int i, c, j; 57 int i, c, j;
@@ -158,7 +157,7 @@ static int create_strip_zones (mddev_t *mddev)
158 } 157 }
159 zone->nb_dev = cnt; 158 zone->nb_dev = cnt;
160 zone->sectors = smallest->sectors * cnt; 159 zone->sectors = smallest->sectors * cnt;
161 zone->zone_start = 0; 160 zone->zone_end = zone->sectors;
162 161
163 current_start = smallest->sectors; 162 current_start = smallest->sectors;
164 curr_zone_start = zone->sectors; 163 curr_zone_start = zone->sectors;
@@ -198,14 +197,13 @@ static int create_strip_zones (mddev_t *mddev)
198 printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n", 197 printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n",
199 zone->nb_dev, (unsigned long long)zone->sectors); 198 zone->nb_dev, (unsigned long long)zone->sectors);
200 199
201 zone->zone_start = curr_zone_start; 200 zone->zone_end = curr_zone_start + zone->sectors;
202 curr_zone_start += zone->sectors; 201 curr_zone_start += zone->sectors;
203 202
204 current_start = smallest->sectors; 203 current_start = smallest->sectors;
205 printk(KERN_INFO "raid0: current zone start: %llu\n", 204 printk(KERN_INFO "raid0: current zone start: %llu\n",
206 (unsigned long long)current_start); 205 (unsigned long long)current_start);
207 } 206 }
208
209 /* Now find appropriate hash spacing. 207 /* Now find appropriate hash spacing.
210 * We want a number which causes most hash entries to cover 208 * We want a number which causes most hash entries to cover
211 * at most two strips, but the hash table must be at most 209 * at most two strips, but the hash table must be at most
@@ -398,6 +396,19 @@ static int raid0_stop (mddev_t *mddev)
398 return 0; 396 return 0;
399} 397}
400 398
399/* Find the zone which holds a particular offset */
400static struct strip_zone *find_zone(struct raid0_private_data *conf,
401 sector_t sector)
402{
403 int i;
404 struct strip_zone *z = conf->strip_zone;
405
406 for (i = 0; i < conf->nr_strip_zones; i++)
407 if (sector < z[i].zone_end)
408 return z + i;
409 BUG();
410}
411
401static int raid0_make_request (struct request_queue *q, struct bio *bio) 412static int raid0_make_request (struct request_queue *q, struct bio *bio)
402{ 413{
403 mddev_t *mddev = q->queuedata; 414 mddev_t *mddev = q->queuedata;
@@ -443,22 +454,11 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
443 bio_pair_release(bp); 454 bio_pair_release(bp);
444 return 0; 455 return 0;
445 } 456 }
446 457 zone = find_zone(conf, sector);
447
448 {
449 sector_t x = sector >> conf->sector_shift;
450 sector_div(x, (u32)conf->spacing);
451 zone = conf->hash_table[x];
452 }
453
454 while (sector >= zone->zone_start + zone->sectors)
455 zone++;
456
457 sect_in_chunk = bio->bi_sector & (chunk_sects - 1); 458 sect_in_chunk = bio->bi_sector & (chunk_sects - 1);
458
459
460 { 459 {
461 sector_t x = (sector - zone->zone_start) >> chunksect_bits; 460 sector_t x = (zone->sectors + sector - zone->zone_end)
461 >> chunksect_bits;
462 462
463 sector_div(x, zone->nb_dev); 463 sector_div(x, zone->nb_dev);
464 chunk = x; 464 chunk = x;
@@ -503,8 +503,8 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
503 seq_printf(seq, "%s/", bdevname( 503 seq_printf(seq, "%s/", bdevname(
504 conf->strip_zone[j].dev[k]->bdev,b)); 504 conf->strip_zone[j].dev[k]->bdev,b));
505 505
506 seq_printf(seq, "] zs=%d ds=%d s=%d\n", 506 seq_printf(seq, "] ze=%d ds=%d s=%d\n",
507 conf->strip_zone[j].zone_start, 507 conf->strip_zone[j].zone_end,
508 conf->strip_zone[j].dev_start, 508 conf->strip_zone[j].dev_start,
509 conf->strip_zone[j].sectors); 509 conf->strip_zone[j].sectors);
510 } 510 }
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index 824b12eb1d4f..556666fec3a5 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -3,7 +3,7 @@
3 3
4struct strip_zone 4struct strip_zone
5{ 5{
6 sector_t zone_start; /* Zone offset in md_dev (in sectors) */ 6 sector_t zone_end; /* Start of the next zone (in sectors) */
7 sector_t dev_start; /* Zone offset in real dev (in sectors) */ 7 sector_t dev_start; /* Zone offset in real dev (in sectors) */
8 sector_t sectors; /* Zone size in sectors */ 8 sector_t sectors; /* Zone size in sectors */
9 int nb_dev; /* # of devices attached to the zone */ 9 int nb_dev; /* # of devices attached to the zone */