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>
This commit is contained in:
NeilBrown 2009-10-16 17:43:51 +11:00
parent eba7152931
commit 82f2d6abf0
1 changed files with 32 additions and 11 deletions

43
Grow.c
View File

@ -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 >= last_block)
return 0;
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;
}
/* needed to recover critical section! */
return 1;
}