From f897078e8b250d1534a31e111e3168e82bfe532b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 26 Jan 2011 08:47:06 +1000 Subject: [PATCH] Fix some issues with setting 'new' state of a reshape - when reshaping a container, ->reshape_active is already set even though it isn't really active yet, so we need to set the new geometry even when reshape_active is set. This is safe. - When restarting a reshape, make sure the reshape_position is set appropriately when external metadata is used. Signed-off-by: NeilBrown --- Grow.c | 25 ++++++++++++++++--------- sysfs.c | 9 +++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Grow.c b/Grow.c index d0df6bd5..42ef17ce 100644 --- a/Grow.c +++ b/Grow.c @@ -1868,19 +1868,23 @@ started: sra->new_chunk = info->new_chunk; - sra->reshape_progress = 0; - if (reshape.after.data_disks < reshape.before.data_disks) - /* start from the end of the new array */ - sra->reshape_progress = (sra->component_size - * reshape.after.data_disks); - if (info->reshape_active) sra->reshape_progress = info->reshape_progress; - else if (info->array.chunk_size == info->new_chunk && + else { + sra->reshape_progress = 0; + if (reshape.after.data_disks < reshape.before.data_disks) + /* start from the end of the new array */ + sra->reshape_progress = (sra->component_size + * reshape.after.data_disks); + } + + if (info->array.chunk_size == info->new_chunk && reshape.before.layout == reshape.after.layout && st->ss->external == 0) { + /* use SET_ARRAY_INFO but only if reshape hasn't started */ array.raid_disks = reshape.after.data_disks + reshape.parity; - if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { + if (!info->reshape_active && + ioctl(fd, SET_ARRAY_INFO, &array) != 0) { int err = errno; fprintf(stderr, @@ -1897,7 +1901,10 @@ started: } } else { /* set them all just in case some old 'new_*' value - * persists from some earlier problem + * persists from some earlier problem. + * We even set them when restarting in the middle. They will + * already be set in that case so this will be a no-op, + * but it is hard to tell the difference. */ int err = 0; if (sysfs_set_num(sra, NULL, "chunk_size", info->new_chunk) < 0) diff --git a/sysfs.c b/sysfs.c index a9ece82b..f0773d47 100644 --- a/sysfs.c +++ b/sysfs.c @@ -569,6 +569,15 @@ int sysfs_set_array(struct mdinfo *info, int vers) if (info->array.level > 0) rv |= sysfs_set_num(info, NULL, "resync_start", info->resync_start); + + if (info->reshape_active) { + rv |= sysfs_set_num(info, NULL, "reshape_position", + info->reshape_progress); + rv |= sysfs_set_num(info, NULL, "chunk_size", info->new_chunk); + /* Don't set layout or raid_disks here as they require some + * analysis and are set by reshape_array + */ + } return rv; } -- 2.39.2