diff options
author | NeilBrown <neilb@suse.de> | 2009-10-16 17:43:51 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-10-16 17:43:51 +1100 |
commit | 82f2d6abf0c1614cf96ff3666e42daf71695afbf (patch) | |
tree | 92a4894bd65c96e9f9055db89f8cc9021e6fcf95 /Grow.c | |
parent | eba7152931708db1d3049030e0a1ffa4ed174373 (diff) |
Grow_restart to handle reducing number of devices in an array.
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>
Diffstat (limited to 'Grow.c')
-rw-r--r-- | Grow.c | 41 |
1 files changed, 31 insertions, 10 deletions
@@ -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; } |