__u32 filler[IMSM_DISK_FILLERS]; /* 0xF4 - 0x107 MPB_DISK_FILLERS for future expansion */
};
+/* map selector for map managment
+ */
+#define MAP_0 2
+#define MAP_1 4
+
/* RAID map configuration infos. */
struct imsm_map {
__u32 pba_of_lba0; /* start address of partition */
{
/* A device can have 2 maps if it is in the middle of a migration.
* If second_map is:
+ * MAP_0 or
* 0 - we return the first map
+ * MAP_1 or
* 1 - we return the second map if it exists, else NULL
* -1 - we return the second map if it exists, else the first
* -2 - we return longer map /excluding uninitialized state/
map2 = (void *)map + sizeof_imsm_map(map);
switch (second_map) {
+ case MAP_0:
case 0:
break;
+ case MAP_1:
case 1:
map = map2;
break;
}
}
-static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, int failed);
-static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev);
+static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
+ int failed, int look_in_map);
+
+static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev,
+ int look_in_map);
+
+static void manage_second_map(struct intel_super *super, struct imsm_dev *dev)
+{
+ if (is_gen_migration(dev)) {
+ int failed;
+ __u8 map_state;
+ struct imsm_map *map2 = get_imsm_map(dev, MAP_1);
+
+ failed = imsm_count_failed(super, dev, MAP_1);
+ map_state = imsm_check_degraded(super, dev, failed,
+ MAP_1);
+ if (map2->map_state != map_state) {
+ map2->map_state = map_state;
+ super->updates_pending++;
+ }
+ }
+}
static struct imsm_disk *get_imsm_missing(struct intel_super *super, __u8 index)
{
struct imsm_map *map;
__u8 state;
- failed = imsm_count_failed(super, dev);
- state = imsm_check_degraded(super, dev, failed);
+ failed = imsm_count_failed(super, dev, MAP_0);
+ state = imsm_check_degraded(super, dev, failed, MAP_0);
map = get_imsm_map(dev, 0);
/* any newly missing disks?
}
-static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, int failed)
+static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
+ int failed, int look_in_map)
{
- struct imsm_map *map = get_imsm_map(dev, 0);
+ struct imsm_map *map;
+
+ map = get_imsm_map(dev, look_in_map);
if (!failed)
return map->map_state == IMSM_T_STATE_UNINITIALIZED ?
return map->map_state;
}
-static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev)
+static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev,
+ int look_in_map)
{
int i;
int failed = 0;
for (i = 0; i < map_for_loop->num_members; i++) {
ord = 0;
- if (i < prev->num_members)
+ if ((look_in_map & MAP_1) && (i < prev->num_members))
ord |= __le32_to_cpu(prev->disk_ord_tbl[i]);
- if (i < map->num_members)
+ if ((look_in_map & MAP_0) && (i < map->num_members))
ord |= __le32_to_cpu(map->disk_ord_tbl[i]);
idx = ord_to_idx(ord);
struct intel_super *super = a->container->sb;
struct imsm_dev *dev = get_imsm_dev(super, inst);
struct imsm_map *map = get_imsm_map(dev, 0);
- int failed = imsm_count_failed(super, dev);
- __u8 map_state = imsm_check_degraded(super, dev, failed);
+ int failed = imsm_count_failed(super, dev, MAP_0);
+ __u8 map_state = imsm_check_degraded(super, dev, failed, MAP_0);
__u32 blocks_per_unit;
if (dev->vol.migr_state &&
super->updates_pending++;
}
- failed = imsm_count_failed(super, dev);
- map_state = imsm_check_degraded(super, dev, failed);
+ failed = imsm_count_failed(super, dev, MAP_0);
+ map_state = imsm_check_degraded(super, dev, failed, MAP_0);
/* check if recovery complete, newly degraded, or failed */
if (map_state == IMSM_T_STATE_NORMAL && is_rebuilding(dev)) {
dprintf("degraded\n");
if (a->last_checkpoint >= a->info.component_size)
end_migration(dev, map_state);
+ else
+ manage_second_map(super, dev);
break;
default:
dprintf("failed\n");
dev2 = get_imsm_dev(cont->sb, dev_idx);
if (dev2) {
- state = imsm_check_degraded(cont->sb, dev2, failed);
+ state = imsm_check_degraded(cont->sb, dev2, failed,
+ MAP_0);
if (state == IMSM_T_STATE_FAILED) {
map = get_imsm_map(dev2, 0);
if (!map)
*/
return NULL;
- if (imsm_check_degraded(super, dev, failed) != IMSM_T_STATE_DEGRADED)
+ if (imsm_check_degraded(super, dev, failed, MAP_0) !=
+ IMSM_T_STATE_DEGRADED)
return NULL;
/*
disk->status &= ~SPARE_DISK;
/* mark rebuild */
- to_state = imsm_check_degraded(super, dev, failed);
+ to_state = imsm_check_degraded(super, dev, failed,
+ MAP_0);
if (!second_map_created) {
second_map_created = 1;
map->map_state = IMSM_T_STATE_DEGRADED;
if (u->direction == R10_TO_R0) {
/* Number of failed disks must be half of initial disk number */
- if (imsm_count_failed(super, dev) != (map->num_members / 2))
+ if (imsm_count_failed(super, dev, MAP_0) !=
+ (map->num_members / 2))
return 0;
/* iterate through devices to mark removed disks as spare */