Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45d4582f authored by Sandeep K Sinha's avatar Sandeep K Sinha Committed by NeilBrown
Browse files

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: default avatarSandeep K Sinha <sandeepksinha@gmail.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 070ec55d
Loading
Loading
Loading
Loading
+3 −90
Original line number Original line Diff line number Diff line
@@ -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);
+0 −5
Original line number Original line Diff line number Diff line
@@ -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];
};
};