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);
*
* 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);
*/
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;
}
/* 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++;
} 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)) {
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;