summaryrefslogtreecommitdiff
path: root/super-intel.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-03-08 15:59:09 +1100
committerNeilBrown <neilb@suse.de>2011-03-08 15:59:09 +1100
commit3f83228aa83f00e83c15c1331d9e27c50c7a9fdc (patch)
treee4fb56bf961a40f86e35ba40591336f7bbf17754 /super-intel.c
parente14e59602a3b0d1abd2a88ecc1e5fb895024b3e2 (diff)
imsm: improve getinfo_super when reshape is in progress.
If a reshape (migration) is happening, we might need to modify the information with provide to md so that it can cope with the reshape. For example, if a migration from 4-device RAID0 to 5-device RAID0 is happening, we need to tell md that it is reshape from degraded 5-device RAID4 to degraded 6-device RAID4 so md doesn't handle direct reshape of RAID0. There may be other migrations supported by IMSM that need special treatment here. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/super-intel.c b/super-intel.c
index 86e6bd4f..0091b271 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1756,14 +1756,47 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
info->custom_array_size = __le32_to_cpu(dev->size_high);
info->custom_array_size <<= 32;
info->custom_array_size |= __le32_to_cpu(dev->size_low);
- if (prev_map) {
+ if (prev_map && map->map_state == prev_map->map_state) {
+ info->reshape_active = 1;
info->new_level = get_imsm_raid_level(map);
info->new_layout = imsm_level_to_layout(info->new_level);
info->new_chunk = __le16_to_cpu(map->blocks_per_strip) << 9;
+ info->delta_disks = map->num_members - prev_map->num_members;
+ /* We shape information that we give to md might have to be
+ * modify to cope with md's requirement for reshaping arrays.
+ * For example, when reshaping a RAID0, md requires it to be
+ * presented as a degraded RAID4.
+ * Also if a RAID0 is migrating to a RAID5 we need to specify
+ * the array as already being RAID5, but the 'before' layout
+ * is a RAID4-like layout.
+ */
+ switch (info->array.level) {
+ case 0:
+ switch(info->new_level) {
+ case 0:
+ /* conversion is happening as RAID4 */
+ info->array.level = 4;
+ info->array.raid_disks += 1;
+ break;
+ case 5:
+ /* conversion is happening as RAID5 */
+ info->array.level = 5;
+ info->array.layout = ALGORITHM_PARITY_N;
+ info->array.raid_disks += 1;
+ info->delta_disks -= 1;
+ break;
+ default:
+ /* FIXME error message */
+ info->array.level = UnSet;
+ break;
+ }
+ break;
+ }
} else {
info->new_level = UnSet;
info->new_layout = UnSet;
info->new_chunk = info->array.chunk_size;
+ info->delta_disks = 0;
}
info->disk.major = 0;
info->disk.minor = 0;
@@ -1777,12 +1810,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
__le32_to_cpu(map_to_analyse->blocks_per_member);
memset(info->uuid, 0, sizeof(info->uuid));
info->recovery_start = MaxSector;
- info->reshape_active = (prev_map != NULL) &&
- (map->map_state == prev_map->map_state);
- if (info->reshape_active)
- info->delta_disks = map->num_members - prev_map->num_members;
- else
- info->delta_disks = 0;
info->reshape_progress = 0;
if (map_to_analyse->map_state == IMSM_T_STATE_UNINITIALIZED ||