imsm: FIX: Correct ords merging in end_migration()

Ord's merging should occur when rebuild finishes and final state is other
than expected only /additional failures occur during rebuild/.
Exclude array initialization.
Merging ords on migration finish should never happen.
Any failure during migration should be immediately placed in first
/current/ map, so no merge is necessary.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Adam Kwolek 2011-12-07 13:57:51 +01:00 committed by NeilBrown
parent 04ed49b3cf
commit 809da78e60
1 changed files with 29 additions and 16 deletions

View File

@ -3128,7 +3128,8 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super,
src->map_state = to_state;
}
static void end_migration(struct imsm_dev *dev, __u8 map_state)
static void end_migration(struct imsm_dev *dev, struct intel_super *super,
__u8 map_state)
{
struct imsm_map *map = get_imsm_map(dev, 0);
struct imsm_map *prev = get_imsm_map(dev, dev->vol.migr_state);
@ -3139,16 +3140,28 @@ static void end_migration(struct imsm_dev *dev, __u8 map_state)
*
* FIXME add support for raid-level-migration
*/
for (i = 0; i < prev->num_members; i++)
for (j = 0; j < map->num_members; j++)
/* during online capacity expansion
* disks position can be changed if takeover is used
*/
if (ord_to_idx(map->disk_ord_tbl[j]) ==
ord_to_idx(prev->disk_ord_tbl[i])) {
map->disk_ord_tbl[j] |= prev->disk_ord_tbl[i];
break;
}
if ((map_state != map->map_state) && (is_gen_migration(dev) == 0) &&
(prev->map_state != IMSM_T_STATE_UNINITIALIZED)) {
/* when final map state is other than expected
* merge maps (not for migration)
*/
int failed;
for (i = 0; i < prev->num_members; i++)
for (j = 0; j < map->num_members; j++)
/* during online capacity expansion
* disks position can be changed
* if takeover is used
*/
if (ord_to_idx(map->disk_ord_tbl[j]) ==
ord_to_idx(prev->disk_ord_tbl[i])) {
map->disk_ord_tbl[j] |=
prev->disk_ord_tbl[i];
break;
}
failed = imsm_count_failed(super, dev, MAP_0);
map_state = imsm_check_degraded(super, dev, failed, MAP_0);
}
dev->vol.migr_state = 0;
set_migr_type(dev, 0);
@ -6335,7 +6348,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
*/
if (is_resyncing(dev)) {
dprintf("imsm: mark resync done\n");
end_migration(dev, map_state);
end_migration(dev, super, map_state);
super->updates_pending++;
a->last_checkpoint = 0;
}
@ -6434,7 +6447,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
/* check if recovery complete, newly degraded, or failed */
if (map_state == IMSM_T_STATE_NORMAL && is_rebuilding(dev)) {
end_migration(dev, map_state);
end_migration(dev, super, map_state);
map = get_imsm_map(dev, 0);
map->failed_disk_num = ~0;
super->updates_pending++;
@ -6449,7 +6462,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
} else if (map_state == IMSM_T_STATE_FAILED &&
map->map_state != map_state) {
dprintf("imsm: mark failed\n");
end_migration(dev, map_state);
end_migration(dev, super, map_state);
super->updates_pending++;
a->last_checkpoint = 0;
} else if (is_gen_migration(dev)) {
@ -6459,14 +6472,14 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
case IMSM_T_STATE_NORMAL:
dprintf("normal\n");
if (a->last_checkpoint >= a->info.component_size)
end_migration(dev, map_state);
end_migration(dev, super, map_state);
map = get_imsm_map(dev, 0);
map->failed_disk_num = ~0;
break;
case IMSM_T_STATE_DEGRADED:
dprintf("degraded\n");
if (a->last_checkpoint >= a->info.component_size)
end_migration(dev, map_state);
end_migration(dev, super, map_state);
else
manage_second_map(super, dev);
break;