From 82f2d6abf0c1614cf96ff3666e42daf71695afbf Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 16 Oct 2009 17:43:51 +1100 Subject: [PATCH] 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 --- Grow.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 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 >= 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; }