summaryrefslogtreecommitdiffstats
path: root/Grow.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-10-16 17:43:51 +1100
committerNeilBrown <neilb@suse.de>2009-10-16 17:43:51 +1100
commit82f2d6abf0c1614cf96ff3666e42daf71695afbf (patch)
tree92a4894bd65c96e9f9055db89f8cc9021e6fcf95 /Grow.c
parenteba7152931708db1d3049030e0a1ffa4ed174373 (diff)
downloadmdadm-82f2d6abf0c1614cf96ff3666e42daf71695afbf.tar.gz
mdadm-82f2d6abf0c1614cf96ff3666e42daf71695afbf.tar.xz
mdadm-82f2d6abf0c1614cf96ff3666e42daf71695afbf.zip
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.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/Grow.c b/Grow.c
index 043e28f..9eb637c 100644
--- 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;
}