diff options
author | NeilBrown <neilb@suse.de> | 2011-03-08 15:59:09 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-03-08 15:59:09 +1100 |
commit | 3f83228aa83f00e83c15c1331d9e27c50c7a9fdc (patch) | |
tree | e4fb56bf961a40f86e35ba40591336f7bbf17754 /super-intel.c | |
parent | e14e59602a3b0d1abd2a88ecc1e5fb895024b3e2 (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.c | 41 |
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 || |