]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: FIX: Check correct slots on disk failure
[thirdparty/mdadm.git] / super-intel.c
index 973b22fc5bbb058ff5b28486f8dd5de1b838f347..7f9c64fbb094b161c8272bf09445db32a6ddebd7 100644 (file)
@@ -4522,14 +4522,16 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
                        set_imsm_ord_tbl_ent(map, slot, df->index | IMSM_ORD_REBUILD);
                        if (is_gen_migration(dev)) {
                                struct imsm_map *map2 = get_imsm_map(dev, 1);
-                               if (slot < map2->num_members) {
+                               int slot2 = get_imsm_disk_slot(map2, df->index);
+                               if ((slot2 < map2->num_members) &&
+                                   (slot2 >= 0)) {
                                        __u32 ord2 = get_imsm_ord_tbl_ent(dev,
-                                                                         slot,
+                                                                         slot2,
                                                                          1);
                                        if ((unsigned)df->index ==
                                                               ord_to_idx(ord2))
                                                set_imsm_ord_tbl_ent(map2,
-                                                       slot,
+                                                       slot2,
                                                        df->index |
                                                        IMSM_ORD_REBUILD);
                                }
@@ -5718,6 +5720,25 @@ static int is_rebuilding(struct imsm_dev *dev)
                return 0;
 }
 
+static int is_initializing(struct imsm_dev *dev)
+{
+       struct imsm_map *migr_map;
+
+       if (!dev->vol.migr_state)
+               return 0;
+
+       if (migr_type(dev) != MIGR_INIT)
+               return 0;
+
+       migr_map = get_imsm_map(dev, 1);
+
+       if (migr_map->map_state == IMSM_T_STATE_UNINITIALIZED)
+               return 1;
+
+       return 0;
+
+}
+
 static void update_recovery_start(struct intel_super *super,
                                        struct imsm_dev *dev,
                                        struct mdinfo *array)
@@ -6139,10 +6160,17 @@ static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
 
        disk->status |= FAILED_DISK;
        set_imsm_ord_tbl_ent(map, slot, idx | IMSM_ORD_REBUILD);
-       if (is_gen_migration(dev)) {
+       /* mark failures in second map if second map exists and this disk
+        * in this slot.
+        * This is valid for migration, initialization and rebuild
+        */
+       if (dev->vol.migr_state) {
                struct imsm_map *map2 = get_imsm_map(dev, 1);
-               if (slot < map2->num_members)
-                       set_imsm_ord_tbl_ent(map2, slot,
+               int slot2 = get_imsm_disk_slot(map2, idx);
+
+               if ((slot2 < map2->num_members) &&
+                   (slot2 >= 0))
+                       set_imsm_ord_tbl_ent(map2, slot2,
                                             idx | IMSM_ORD_REBUILD);
        }
        if (map->failed_disk_num == 0xff)
@@ -6169,6 +6197,17 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
                return;
 
        dprintf("imsm: mark missing\n");
+       /* end process for initialization and rebuild only
+        */
+       if (is_gen_migration(dev) == 0) {
+               __u8 map_state;
+               int failed;
+
+               failed = imsm_count_failed(super, dev, MAP_0);
+               map_state = imsm_check_degraded(super, dev, failed, MAP_0);
+
+               end_migration(dev, super, map_state);
+       }
        for (dl = super->missing; dl; dl = dl->next)
                mark_missing(dev, &dl->disk, dl->index);
        super->updates_pending++;
@@ -6501,6 +6540,12 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                        super->updates_pending++;
                        break;
                }
+               if (is_initializing(dev)) {
+                       dprintf("while initialization.");
+                       map->map_state = map_state;
+                       super->updates_pending++;
+                       break;
+               }
        break;
        case IMSM_T_STATE_FAILED: /* transition to failed state */
                dprintf("failed: ");