Use one function chosing spares from container

container_chose_spares in Monitor.c and
get_spares_for_grow in super-intel.c
do the same thing: search for spares in a container.

Another version will also be needed for Incremental
so a more general solution is presented here and
applied in two previous contexts.

Normally domlist==NULL would lead an empty list but
this is typically checked earlier so here it is interpreted
as "do not test domains".

Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Anna Czarnowska 2011-01-05 14:34:14 +11:00 committed by NeilBrown
parent ed7fc6b4d9
commit 326727d9c9
4 changed files with 79 additions and 74 deletions

View File

@ -828,59 +828,34 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
/* This is similar to choose_spare, but we cannot trust devstate,
* so we need to read the metadata instead
*/
struct mdinfo *list;
struct supertype *st = from->metadata;
int fd = open(from->devname, O_RDONLY);
int err;
struct mdinfo *disks, *d;
dev_t dev = 0;
if (fd < 0)
return 0;
if (!st->ss->getinfo_super_disks)
if (!st->ss->getinfo_super_disks) {
close(fd);
return 0;
}
err = st->ss->load_container(st, fd, NULL);
close(fd);
if (err)
return 0;
disks = st->ss->getinfo_super_disks(st);
st->ss->free_super(st);
if (!disks)
return 0;
for (d = disks->devs ; d && !dev ; d = d->next) {
if (d->disk.state == 0) {
struct dev_policy *pol;
unsigned long long dev_size;
dev = makedev(d->disk.major,d->disk.minor);
if (min_size &&
dev_size_from_id(dev, &dev_size) &&
dev_size < min_size) {
dev = 0;
continue;
}
if (from == to)
/* Just checking if destination already has
* a spare, no need to check policy, we are
* done.
*/
break;
pol = devnum_policy(dev);
if (from->spare_group)
pol_add(&pol, pol_domain,
from->spare_group, NULL);
if (!domain_test(domlist, pol, to->metadata->ss->name))
dev = 0;
dev_policy_free(pol);
}
/* We only need one spare so full list not needed */
list = container_choose_spares(st, min_size, domlist, from->spare_group,
to->metadata->ss->name, 1);
if (list) {
struct mdinfo *disks = list->devs;
if (disks)
dev = makedev(disks->disk.major, disks->disk.minor);
sysfs_free(list);
}
sysfs_free(disks);
st->ss->free_super(st);
return dev;
}

View File

@ -1095,7 +1095,11 @@ extern void append_metadata_update(struct supertype *st, void *buf, int len);
extern int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
char *chosen_name, int verbose);
extern struct mdinfo *container_choose_spares(struct supertype *st,
unsigned long long min_size,
struct domainlist *domlist,
char *spare_group,
const char *metadata, int get_one);
extern int add_disk(int mdfd, struct supertype *st,
struct mdinfo *sra, struct mdinfo *info);
extern int remove_disk(int mdfd, struct supertype *st,

View File

@ -6241,42 +6241,8 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
*/
static struct mdinfo *get_spares_for_grow(struct supertype *st)
{
dev_t dev = 0;
struct mdinfo *disks, *d, **dp;
unsigned long long min_size = min_acceptable_spare_size_imsm(st);
/* get list of alldisks in container */
disks = getinfo_super_disks_imsm(st);
if (!disks)
return NULL;
/* find spare devices on the list */
dp = &disks->devs;
disks->array.spare_disks = 0;
while (*dp) {
int found = 0;
d = *dp;
if (d->disk.state == 0) {
/* check if size is acceptable */
unsigned long long dev_size;
dev = makedev(d->disk.major,d->disk.minor);
if (min_size &&
dev_size_from_id(dev, &dev_size) &&
dev_size >= min_size) {
dev = 0;
found = 1;
}
}
if (found) {
dp = &d->next;
disks->array.spare_disks++;
} else {
*dp = d->next;
d->next = NULL;
sysfs_free(d);
}
}
return disks;
return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
}
/******************************************************************************

60
util.c
View File

@ -1909,3 +1909,63 @@ int experimental(void)
}
}
/* Pick all spares matching given criteria from a container
* if min_size == 0 do not check size
* if domlist == NULL do not check domains
* if spare_group given add it to domains of each spare
* metadata allows to test domains using metadata of destination array */
struct mdinfo *container_choose_spares(struct supertype *st,
unsigned long long min_size,
struct domainlist *domlist,
char *spare_group,
const char *metadata, int get_one)
{
struct mdinfo *d, **dp, *disks = NULL;
/* get list of all disks in container */
if (st->ss->getinfo_super_disks)
disks = st->ss->getinfo_super_disks(st);
if (!disks)
return disks;
/* find spare devices on the list */
dp = &disks->devs;
disks->array.spare_disks = 0;
while (*dp) {
int found = 0;
d = *dp;
if (d->disk.state == 0) {
/* check if size is acceptable */
unsigned long long dev_size;
dev_t dev = makedev(d->disk.major,d->disk.minor);
if (!min_size ||
(dev_size_from_id(dev, &dev_size) &&
dev_size >= min_size))
found = 1;
/* check if domain matches */
if (found && domlist) {
struct dev_policy *pol = devnum_policy(dev);
if (spare_group)
pol_add(&pol, pol_domain,
spare_group, NULL);
if (!domain_test(domlist, pol, metadata))
found = 0;
dev_policy_free(pol);
}
}
if (found) {
dp = &d->next;
disks->array.spare_disks++;
if (get_one) {
sysfs_free(*dp);
d->next = NULL;
}
} else {
*dp = d->next;
d->next = NULL;
sysfs_free(d);
}
}
return disks;
}