]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow: check container is idle before freezing it.
authorNeilBrown <neilb@suse.de>
Wed, 15 Dec 2010 22:07:51 +0000 (09:07 +1100)
committerNeilBrown <neilb@suse.de>
Wed, 15 Dec 2010 22:07:51 +0000 (09:07 +1100)
Before we freeze a container in preparation for growing a subarray, we
need to be sure all the subarrays are idle.

This test is racy as recovery could start at any moment following a
failure.  However it is still useful as it stops us from even trying
to start a reshape while a reshape or recovery is active.

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

diff --git a/Grow.c b/Grow.c
index 222d755c81d387de82339a6adc95bf7c67daafa6..af605a86f612c7bd29e4208e1d9081be735eeb6b 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -467,17 +467,41 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long blocks,
                           int disks, int chunk, int level, int layout, int data,
                           int dests, int *destfd, unsigned long long *destoffsets);
 
+static int check_idle(struct supertype *st)
+{
+       /* Check that all member arrays for this container, or the
+        * container of this array, are idle
+        */
+       int container_dev = (st->container_dev != NoMdDev
+                            ? st->container_dev : st->devnum);
+       char container[40];
+       struct mdstat_ent *ent, *e;
+       int is_idle = 1;
+       
+       fmt_devname(container, container_dev);
+       ent = mdstat_read(0, 0);
+       for (e = ent ; e; e = e->next) {
+               if (!is_container_member(e, container))
+                       continue;
+               if (e->percent >= 0) {
+                       is_idle = 0;
+                       break;
+               }
+       }
+       free_mdstat(ent);
+       return is_idle;
+}
+
 static int freeze_container(struct supertype *st)
 {
        int container_dev = (st->container_dev != NoMdDev
                             ? st->container_dev : st->devnum);
-       char *container = devnum2devname(container_dev);
+       char container[40];
 
-       if (!container) {
-               fprintf(stderr, Name
-                       ": could not determine container name, freeze aborted\n");
-               return -2;
-       }
+       if (!check_idle(st))
+               return -1;
+       
+       fmt_devname(container, container_dev);
 
        if (block_monitor(container, 1)) {
                fprintf(stderr, Name ": failed to freeze container\n");
@@ -491,13 +515,9 @@ static void unfreeze_container(struct supertype *st)
 {
        int container_dev = (st->container_dev != NoMdDev
                             ? st->container_dev : st->devnum);
-       char *container = devnum2devname(container_dev);
-
-       if (!container) {
-               fprintf(stderr, Name
-                       ": could not determine container name, unfreeze aborted\n");
-               return;
-       }
+       char container[40];
+       
+       fmt_devname(container, container_dev);
 
        unblock_monitor(container, 1);
 }