summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandeep K Sinha <sandeepksinha@gmail.com>2009-06-16 10:55:26 +0400
committerNeilBrown <neilb@suse.de>2009-06-16 10:55:26 +0400
commit45d4582f219619e368ea91ea1189085e1c5f1969 (patch)
tree15c38d1090d67ecb600c395a5155f2630804d851
parent070ec55d07157a3041f92654135c3c6e2eaaf901 (diff)
downloadlinux-45d4582f219619e368ea91ea1189085e1c5f1969.tar.xz
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>
-rw-r--r--drivers/md/linear.c93
-rw-r--r--drivers/md/linear.h5
2 files changed, 3 insertions, 95 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)
{
dev_info_t *hash;
linear_conf_t *conf = mddev->private;
- sector_t idx = sector >> conf->sector_shift;
- /*
- * sector_div(a,b) returns the remainer and sets a to a/b
- */
- (void)sector_div(idx, conf->spacing);
- hash = conf->hash_table[idx];
+ hash = conf->disks;
while (sector >= hash->num_sectors + hash->start_sector)
hash++;
@@ -114,11 +109,8 @@ static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
{
linear_conf_t *conf;
- dev_info_t **table;
mdk_rdev_t *rdev;
- int i, nb_zone, cnt;
- sector_t min_sectors;
- sector_t curr_sector;
+ int i, cnt;
conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
GFP_KERNEL);
@@ -159,63 +151,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
goto out;
}
- min_sectors = conf->array_sectors;
- sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
- if (min_sectors == 0)
- min_sectors = 1;
-
- /* min_sectors is the minimum spacing that will fit the hash
- * table in one PAGE. This may be much smaller than needed.
- * We find the smallest non-terminal set of consecutive devices
- * that is larger than min_sectors and use the size of that as
- * the actual spacing
- */
- conf->spacing = conf->array_sectors;
- for (i=0; i < cnt-1 ; i++) {
- sector_t tmp = 0;
- int j;
- for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
- tmp += conf->disks[j].num_sectors;
- if (tmp >= min_sectors && tmp < conf->spacing)
- conf->spacing = tmp;
- }
-
- /* spacing may be too large for sector_div to work with,
- * so we might need to pre-shift
- */
- conf->sector_shift = 0;
- if (sizeof(sector_t) > sizeof(u32)) {
- sector_t space = conf->spacing;
- while (space > (sector_t)(~(u32)0)) {
- space >>= 1;
- conf->sector_shift++;
- }
- }
/*
- * This code was restructured to work around a gcc-2.95.3 internal
- * compiler error. Alter it with care.
- */
- {
- sector_t sz;
- unsigned round;
- unsigned long base;
-
- sz = conf->array_sectors >> conf->sector_shift;
- sz += 1; /* force round-up */
- base = conf->spacing >> conf->sector_shift;
- round = sector_div(sz, base);
- nb_zone = sz + (round ? 1 : 0);
- }
- BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
-
- conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
- GFP_KERNEL);
- if (!conf->hash_table)
- goto out;
-
- /*
- * Here we generate the linear hash table
- * First calculate the device offsets.
+ * Here we calculate the device offsets.
*/
conf->disks[0].start_sector = 0;
for (i = 1; i < raid_disks; i++)
@@ -223,29 +160,6 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
conf->disks[i-1].start_sector +
conf->disks[i-1].num_sectors;
- table = conf->hash_table;
- i = 0;
- for (curr_sector = 0;
- curr_sector < conf->array_sectors;
- curr_sector += conf->spacing) {
-
- while (i < raid_disks-1 &&
- curr_sector >= conf->disks[i+1].start_sector)
- i++;
-
- *table ++ = conf->disks + i;
- }
-
- if (conf->sector_shift) {
- conf->spacing >>= conf->sector_shift;
- /* round spacing up so that when we divide by it,
- * we err on the side of "too-low", which is safest.
- */
- conf->spacing++;
- }
-
- BUG_ON(table - conf->hash_table > nb_zone);
-
return conf;
out:
@@ -309,7 +223,6 @@ static int linear_stop (mddev_t *mddev)
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
do {
linear_conf_t *t = conf->prev;
- kfree(conf->hash_table);
kfree(conf);
conf = t;
} while (conf);
diff --git a/drivers/md/linear.h b/drivers/md/linear.h
index 76078f1cded0..721a878403d1 100644
--- a/drivers/md/linear.h
+++ b/drivers/md/linear.h
@@ -12,12 +12,7 @@ typedef struct dev_info dev_info_t;
struct linear_private_data
{
struct linear_private_data *prev; /* earlier version */
- dev_info_t **hash_table;
- sector_t spacing;
sector_t array_sectors;
- int sector_shift; /* shift before dividing
- * by spacing
- */
dev_info_t disks[0];
};