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>
This commit is contained in:
committed by
NeilBrown
parent
070ec55d07
commit
45d4582f21
@@ -29,13 +29,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
|
|||||||
{
|
{
|
||||||
dev_info_t *hash;
|
dev_info_t *hash;
|
||||||
linear_conf_t *conf = mddev->private;
|
linear_conf_t *conf = mddev->private;
|
||||||
sector_t idx = sector >> conf->sector_shift;
|
|
||||||
|
|
||||||
/*
|
hash = conf->disks;
|
||||||
* sector_div(a,b) returns the remainer and sets a to a/b
|
|
||||||
*/
|
|
||||||
(void)sector_div(idx, conf->spacing);
|
|
||||||
hash = conf->hash_table[idx];
|
|
||||||
|
|
||||||
while (sector >= hash->num_sectors + hash->start_sector)
|
while (sector >= hash->num_sectors + hash->start_sector)
|
||||||
hash++;
|
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)
|
static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
|
||||||
{
|
{
|
||||||
linear_conf_t *conf;
|
linear_conf_t *conf;
|
||||||
dev_info_t **table;
|
|
||||||
mdk_rdev_t *rdev;
|
mdk_rdev_t *rdev;
|
||||||
int i, nb_zone, cnt;
|
int i, cnt;
|
||||||
sector_t min_sectors;
|
|
||||||
sector_t curr_sector;
|
|
||||||
|
|
||||||
conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
|
conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
@@ -159,63 +151,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
|
|||||||
goto out;
|
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
|
* Here we calculate the device offsets.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
conf->disks[0].start_sector = 0;
|
conf->disks[0].start_sector = 0;
|
||||||
for (i = 1; i < raid_disks; i++)
|
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].start_sector +
|
||||||
conf->disks[i-1].num_sectors;
|
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;
|
return conf;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -309,7 +223,6 @@ static int linear_stop (mddev_t *mddev)
|
|||||||
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
|
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
|
||||||
do {
|
do {
|
||||||
linear_conf_t *t = conf->prev;
|
linear_conf_t *t = conf->prev;
|
||||||
kfree(conf->hash_table);
|
|
||||||
kfree(conf);
|
kfree(conf);
|
||||||
conf = t;
|
conf = t;
|
||||||
} while (conf);
|
} while (conf);
|
||||||
|
@@ -12,12 +12,7 @@ typedef struct dev_info dev_info_t;
|
|||||||
struct linear_private_data
|
struct linear_private_data
|
||||||
{
|
{
|
||||||
struct linear_private_data *prev; /* earlier version */
|
struct linear_private_data *prev; /* earlier version */
|
||||||
dev_info_t **hash_table;
|
|
||||||
sector_t spacing;
|
|
||||||
sector_t array_sectors;
|
sector_t array_sectors;
|
||||||
int sector_shift; /* shift before dividing
|
|
||||||
* by spacing
|
|
||||||
*/
|
|
||||||
dev_info_t disks[0];
|
dev_info_t disks[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user