]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Monitor: teach spare migration about containers
authorNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
When trying to move a spare, move to the container of a degraded
array, not to the array itself.
And don't try to move from a subarray, only from a native or container
array.
And don't move from a container which contains degraded subarrays.

Signed-off-by: NeilBrown <neilb@suse.de>
Monitor.c

index ba6735c4b139eece19ec0d95fb028b43cbf3e101..793087e0a37c94224e7ccf438e2c286b6d19c514 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -740,10 +740,22 @@ static int move_spare(struct state *from, struct state *to,
 static int check_donor(struct state *from, struct state *to,
                       struct domainlist *domlist)
 {
+       struct state *sub;
+
        if (from == to)
                return 0;
-       if (from->active < from->raid)
+       if (from->parent)
+               /* Cannot move from a member */
                return 0;
+       for (sub = from->subarray; sub; sub = sub->subarray)
+               /* If source array has degraded subarrays, don't
+                * remove anything
+                */
+               if (sub->active < sub->raid)
+                       return 0;
+       if (from->metadata->ss->external == 0)
+               if (from->active < from->raid)
+                       return 0;
        if (from->spare <= 0)
                return 0;
        if (domlist == NULL)
@@ -753,14 +765,20 @@ static int check_donor(struct state *from, struct state *to,
 
 static void try_spare_migration(struct state *statelist, struct alert_info *info)
 {
-       struct state *from, *to;
+       struct state *from;
+       struct state *st;
 
        link_containers_with_subarrays(statelist);
-       for (to = statelist; to; to = to->next)
-               if (to->active < to->raid &&
-                   to->spare == 0) {
+       for (st = statelist; st; st = st->next)
+               if (st->active < st->raid &&
+                   st->spare == 0) {
                        struct domainlist *domlist = NULL;
                        int d;
+                       struct state *to = st;
+
+                       if (to->parent)
+                               /* member of a container */
+                               to = to->parent;
 
                        for (d = 0; d < MaxDisks; d++)
                                if (to->devid[d])