]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow_restart to handle reducing number of devices in an array.
authorNeilBrown <neilb@suse.de>
Fri, 16 Oct 2009 06:43:51 +0000 (17:43 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 16 Oct 2009 06:43:51 +0000 (17:43 +1100)
FIXME this is wrong . what direction does reshape_position move?

If the device count in an array is shrinking, the critical
region is different so the tests need to be different when
restarting.

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

diff --git a/Grow.c b/Grow.c
index 043e28ff37da294de8de27ca3562017e69f4e496..9eb637c9f795f351313c52db9919790070d5d2fa 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1543,7 +1543,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt
        int i, j;
        int old_disks;
        unsigned long long *offsets;
-       unsigned long long  nstripe, ostripe, last_block;
+       unsigned long long  nstripe, ostripe;
        int ndata, odata;
 
        if (info->new_level != info->array.level)
@@ -1734,17 +1734,38 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt
        if (info->delta_disks == 0)
                /* Alway need backup data when size doesn't change */
                return 1;
-       nstripe = ostripe = 0;
-       last_block = 0;
-       while (nstripe >= ostripe) {
-               nstripe += info->new_chunk / 512;
-               last_block = nstripe * ndata;
-               ostripe = last_block / odata / (info->array.chunk_size/512) *
-                       (info->array.chunk_size/512);
+       if (info->delta_disks < 0) {
+               /* When shrinking, the critical section is at the end.
+                * So see if we are before the critical section.
+                */
+               unsigned long long first_block;
+               nstripe = ostripe = 0;
+               first_block = 0;
+               while (ostripe >= nstripe) {
+                       ostripe += info->array.chunk_size / 512;
+                       first_block = ostripe * odata;
+                       nstripe = first_block / ndata / (info->new_chunk/512) *
+                               (info->new_chunk/512);
+               }
+
+               if (info->reshape_progress >= first_block)
+                       return 0;
        }
+       if (info->delta_disks > 0) {
+               /* See if we are beyond the critical section. */
+               unsigned long long last_block;
+               nstripe = ostripe = 0;
+               last_block = 0;
+               while (nstripe >= ostripe) {
+                       nstripe += info->new_chunk / 512;
+                       last_block = nstripe * ndata;
+                       ostripe = last_block / odata / (info->array.chunk_size/512) *
+                               (info->array.chunk_size/512);
+               }
 
-       if (info->reshape_progress >= last_block)
-               return 0;
+               if (info->reshape_progress >= last_block)
+                       return 0;
+       }
        /* needed to recover critical section! */
        return 1;
 }