]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Monitor: don't add more spares than needed
authorAnna Czarnowska <anna.czarnowska@intel.com>
Fri, 3 Dec 2010 03:11:29 +0000 (14:11 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 3 Dec 2010 03:11:29 +0000 (14:11 +1100)
When we add a spare to a container it takes a while
before it is noticed by mdmon and recovery starts.
During this time the array remains degraded but we don't want to add
any more spares to this container. Therefore we must check container
with degraded array if it doesn't already have a suitable spare.
container_choose_spare is reused with from=to
Domain check is not needed in this situation.

Ping_manager after moving disk is needed to be able to see
newly added disk in container after coming back through the loop.

Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Monitor.c

index 8f1bfea963e40c11820d22ad0ad7d36edde3d537..61550ee00b83cd1dc77c5302321e2b3433d7f8ef 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -743,6 +743,11 @@ static int move_spare(struct state *from, struct state *to,
                devlist.disposition = 'a';
                if (Manage_subdevs(to->devname, fd1, &devlist, -1, 0) == 0) {
                        alert("MoveSpare", to->devname, from->devname, info);
+                       /* make sure we will see newly added spare before next
+                        * time through loop
+                        */
+                       ping_manager(to->devname);
+                       ping_manager(from->devname);
                        close(fd1);
                        close(fd2);
                        return 1;
@@ -853,13 +858,20 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
                                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);
                }
        }
@@ -887,6 +899,15 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
                                to = to->parent;
 
                        min_size = min_spare_size_required(to);
+                       if (to->metadata->ss->external) {
+                               /* We must make sure there is
+                                * no suitable spare in container already.
+                                * If there is we don't add more */
+                               dev_t devid = container_choose_spare(
+                                       to, to, NULL, min_size);
+                               if (devid > 0)
+                                       continue;
+                       }
                        for (d = 0; d < MaxDisks; d++)
                                if (to->devid[d])
                                        domainlist_add_dev(&domlist,