diff options
author | NeilBrown <neilb@suse.de> | 2010-11-22 20:58:07 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-11-22 20:58:07 +1100 |
commit | e78dda3bf5ff840b65e85dbd7fc24ec4ccd291a5 (patch) | |
tree | da8f35e89c6ea9ee90ca54674a416fdfa67dd044 | |
parent | 2feb22efbc216e53486cc20c05df13f8340a9d49 (diff) |
Monitor: policy based spare migration.
Rather than only migrating between arrays with the same spare_group,
we now migrate based on domains set in the policy.
In order for spare_group to continue to work, we treat it as a domain
of the destination array, and a domain of any device we might remove
from a source array.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | Monitor.c | 62 | ||||
-rw-r--r-- | mdadm.h | 6 | ||||
-rw-r--r-- | policy.c | 36 |
3 files changed, 73 insertions, 31 deletions
@@ -681,15 +681,16 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state *statelist, return new_found; } -static int move_spare(struct state *st2, struct state *st, +static int move_spare(struct state *from, struct state *to, + struct domainlist *domlist, struct alert_info *info) { struct mddev_dev devlist; char devname[20]; /* try to remove and add */ - int fd1 = open(st->devname, O_RDONLY); - int fd2 = open(st2->devname, O_RDONLY); + int fd1 = open(to->devname, O_RDONLY); + int fd2 = open(from->devname, O_RDONLY); int dev = -1; int d; if (fd1 < 0 || fd2 < 0) { @@ -697,11 +698,14 @@ static int move_spare(struct state *st2, struct state *st, if (fd2>=0) close(fd2); return 0; } - for (d=st2->raid; d < MaxDisks; d++) { - if (st2->devid[d] > 0 && - st2->devstate[d] == 0) { - dev = st2->devid[d]; - break; + for (d = from->raid; dev < 0 && d < MaxDisks; d++) { + if (from->devid[d] > 0 && + from->devstate[d] == 0) { + struct dev_policy *pol = devnum_policy(from->devid[d]); + pol_add(&pol, pol_domain, from->spare_group, NULL); + if (domain_test(domlist, pol, to->metadata->ss->name)) + dev = from->devid[d]; + dev_policy_free(pol); } } if (dev < 0) { @@ -718,22 +722,23 @@ static int move_spare(struct state *st2, struct state *st, sprintf(devname, "%d:%d", major(dev), minor(dev)); devlist.disposition = 'r'; - if (Manage_subdevs(st2->devname, fd2, &devlist, -1, 0) == 0) { + if (Manage_subdevs(from->devname, fd2, &devlist, -1, 0) == 0) { devlist.disposition = 'a'; - if (Manage_subdevs(st->devname, fd1, &devlist, -1, 0) == 0) { - alert("MoveSpare", st->devname, st2->devname, info); + if (Manage_subdevs(to->devname, fd1, &devlist, -1, 0) == 0) { + alert("MoveSpare", to->devname, from->devname, info); close(fd1); close(fd2); return 1; } - else Manage_subdevs(st2->devname, fd2, &devlist, -1, 0); + else Manage_subdevs(from->devname, fd2, &devlist, -1, 0); } close(fd1); close(fd2); return 0; } -static int check_donor(struct state *from, struct state *to) +static int check_donor(struct state *from, struct state *to, + struct domainlist *domlist) { if (from == to) return 0; @@ -741,24 +746,35 @@ static int check_donor(struct state *from, struct state *to) return 0; if (from->spare <= 0) return 0; - if (!from->spare_group || !to->spare_group) + if (domlist == NULL) return 0; - return (strcmp(from->spare_group, to->spare_group) == 0); + return 1; } static void try_spare_migration(struct state *statelist, struct alert_info *info) { - struct state *st; + struct state *from, *to; link_containers_with_subarrays(statelist); - for (st = statelist; st; st=st->next) - if (st->active < st->raid && - st->spare == 0) { - struct state *st2; - for (st2=statelist ; st2 ; st2=st2->next) - if (check_donor(st2, st) - && move_spare(st2, st, info)) + for (to = statelist; to; to = to->next) + if (to->active < to->raid && + to->spare == 0) { + struct domainlist *domlist = NULL; + int d; + + for (d = 0; d < MaxDisks; d++) + if (to->devid[d]) + domainlist_add_dev(&domlist, + to->devid[d], + to->metadata->ss->name); + if (to->spare_group) + domain_add(&domlist, to->spare_group); + + for (from=statelist ; from ; from=from->next) + if (check_donor(from, to, domlist) + && move_spare(from, to, domlist, info)) break; + domain_free(domlist); } } @@ -811,7 +811,8 @@ extern struct dev_policy *disk_policy(struct mdinfo *disk); extern struct dev_policy *devnum_policy(int dev); extern void dev_policy_free(struct dev_policy *p); -extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata); +//extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata); +extern void pol_add(struct dev_policy **pol, char *name, char *val, char *metadata); extern struct dev_policy *pol_find(struct dev_policy *pol, char *name); enum policy_action { @@ -839,9 +840,12 @@ extern int domain_test(struct domainlist *dom, struct dev_policy *pol, const char *metadata); extern struct domainlist *domain_from_array(struct mdinfo *mdi, const char *metadata); +extern void domainlist_add_dev(struct domainlist **dom, int devnum, + const char *metadata); extern void domain_free(struct domainlist *dl); extern void domain_merge(struct domainlist **domp, struct dev_policy *pol, const char *metadata); +void domain_add(struct domainlist **domp, char *domain); extern void policy_save_path(char *id_path, struct map_ent *array); extern int policy_check_path(struct mdinfo *disk, struct map_ent *array); @@ -40,7 +40,7 @@ * particularly from a set of policy rules in mdadm.conf */ -void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata) +static void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata) { struct dev_policy *n = malloc(sizeof(*n)); const char *real_metadata = NULL; @@ -365,6 +365,16 @@ struct dev_policy *path_policy(char *path, char *type) return pol; } +void pol_add(struct dev_policy **pol, + char *name, char *val, + char *metadata) +{ + pol_new(pol, name, val, metadata); + pol_sort(pol); + pol_dedup(*pol); +} + + /* * disk_policy() gathers policy information for the * disk described in the given mdinfo (disk.{major,minor}). @@ -600,7 +610,7 @@ void domain_merge(struct domainlist **domp, struct dev_policy *pollist, struct dev_policy *pol; pollist = pol_find(pollist, pol_domain); pol_for_each(pol, pollist, metadata) - domp = domain_merge_one(domp, pol->value); + domain_merge_one(domp, pol->value); } int domain_test(struct domainlist *dom, struct dev_policy *pol, @@ -625,19 +635,31 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol, return found_any; } +void domainlist_add_dev(struct domainlist **dom, int devnum, const char *metadata) +{ + struct dev_policy *pol = devnum_policy(devnum); + domain_merge(dom, pol, metadata); + dev_policy_free(pol); +} + struct domainlist *domain_from_array(struct mdinfo *mdi, const char *metadata) { struct domainlist *domlist = NULL; - for (mdi = mdi->devs ; mdi ; mdi = mdi->next) { - struct dev_policy *pol = disk_policy(mdi); + for (mdi = mdi->devs ; mdi ; mdi = mdi->next) + domainlist_add_dev(&domlist, makedev(mdi->disk.major, + mdi->disk.minor), + metadata); - domain_merge(&domlist, pol, metadata); - dev_policy_free(pol); - } return domlist; } +void domain_add(struct domainlist **domp, char *domain) +{ + domain_merge_one(domp, domain); +} + + void domain_free(struct domainlist *dl) { while (dl) { |