]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
FIX: Typo error in fprint command
[thirdparty/mdadm.git] / super-intel.c
index 217a1963eec7f489b2b50814d9772c9611472132..0e9269f5deea81b161569cc3395f30608bdb4e81 100644 (file)
@@ -108,8 +108,9 @@ struct imsm_disk {
 
 /* map selector for map managment
  */
-#define MAP_0          2
-#define MAP_1          4
+#define MAP_0          0
+#define MAP_1          1
+#define MAP_X          -1
 
 /* RAID map configuration infos. */
 struct imsm_map {
@@ -239,6 +240,12 @@ static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed"
 
 #define GEN_MIGR_AREA_SIZE 2048 /* General Migration Copy Area size in blocks */
 
+#define MIGR_REC_BUF_SIZE 512 /* size of migr_record i/o buffer */
+#define MIGR_REC_POSITION 512 /* migr_record position offset on disk,
+                              * MIGR_REC_BUF_SIZE <= MIGR_REC_POSITION
+                              */
+
+
 #define UNIT_SRC_NORMAL     0   /* Source data for curr_migr_unit must
                                 *  be recovered using srcMap */
 #define UNIT_SRC_IN_CP_AREA 1   /* Source data for curr_migr_unit has
@@ -667,9 +674,9 @@ struct imsm_map *get_imsm_map(struct imsm_dev *dev, int second_map)
 {
        /* 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
+        *    MAP_0 - we return the first map
+        *    MAP_1 - we return the second map if it exists, else NULL
+        *    MAP_X - we return the second map if it exists, else the first
         */
        struct imsm_map *map = &dev->vol.map[0];
        struct imsm_map *map2 = NULL;
@@ -679,13 +686,11 @@ struct imsm_map *get_imsm_map(struct imsm_dev *dev, int second_map)
 
        switch (second_map) {
        case MAP_0:
-       case 0:
                break;
        case MAP_1:
-       case 1:
                map = map2;
                break;
-       case -1:
+       case MAP_X:
                if (map2)
                        map = map2;
                break;
@@ -702,13 +707,13 @@ struct imsm_map *get_imsm_map(struct imsm_dev *dev, int second_map)
 static size_t sizeof_imsm_dev(struct imsm_dev *dev, int migr_state)
 {
        size_t size = sizeof(*dev) - sizeof(struct imsm_map) +
-                     sizeof_imsm_map(get_imsm_map(dev, 0));
+                     sizeof_imsm_map(get_imsm_map(dev, MAP_0));
 
        /* migrating means an additional map */
        if (dev->vol.migr_state)
-               size += sizeof_imsm_map(get_imsm_map(dev, 1));
+               size += sizeof_imsm_map(get_imsm_map(dev, MAP_1));
        else if (migr_state)
-               size += sizeof_imsm_map(get_imsm_map(dev, 0));
+               size += sizeof_imsm_map(get_imsm_map(dev, MAP_0));
 
        return size;
 }
@@ -762,9 +767,9 @@ static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
 
 /*
  * for second_map:
- *  == 0 get first map
- *  == 1 get second map
- *  == -1 than get map according to the current migr_state
+ *  == MAP_0 get first map
+ *  == MAP_1 get second map
+ *  == MAP_X than get map according to the current migr_state
  */
 static __u32 get_imsm_ord_tbl_ent(struct imsm_dev *dev,
                                  int slot,
@@ -835,7 +840,7 @@ static int count_memberships(struct dl *dl, struct intel_super *super)
 
        for (i = 0; i < super->anchor->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map = get_imsm_map(dev, MAP_0);
 
                if (get_imsm_disk_slot(map, dl->index) >= 0)
                        memberships++;
@@ -870,7 +875,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
 
        for (i = 0; i < super->anchor->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map = get_imsm_map(dev, MAP_0);
 
                if (get_imsm_disk_slot(map, dl->index) >= 0) {
                        e->start = __le32_to_cpu(map->pba_of_lba0);
@@ -1043,8 +1048,8 @@ static void print_imsm_dev(struct intel_super *super,
 {
        __u64 sz;
        int slot, i;
-       struct imsm_map *map = get_imsm_map(dev, 0);
-       struct imsm_map *map2 = get_imsm_map(dev, 1);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
+       struct imsm_map *map2 = get_imsm_map(dev, MAP_1);
        __u32 ord;
 
        printf("\n");
@@ -1060,14 +1065,14 @@ static void print_imsm_dev(struct intel_super *super,
        printf("\n");
        printf("          Slots : [");
        for (i = 0; i < map->num_members; i++) {
-               ord = get_imsm_ord_tbl_ent(dev, i, 0);
+               ord = get_imsm_ord_tbl_ent(dev, i, MAP_0);
                printf("%s", ord & IMSM_ORD_REBUILD ? "_" : "U");
        }
        printf("]");
        if (map2) {
                printf(" <-- [");
                for (i = 0; i < map2->num_members; i++) {
-                       ord = get_imsm_ord_tbl_ent(dev, i, 1);
+                       ord = get_imsm_ord_tbl_ent(dev, i, MAP_1);
                        printf("%s", ord & IMSM_ORD_REBUILD ? "_" : "U");
                }
                printf("]");
@@ -1081,7 +1086,7 @@ static void print_imsm_dev(struct intel_super *super,
        printf("\n");
        slot = get_imsm_disk_slot(map, disk_idx);
        if (slot >= 0) {
-               ord = get_imsm_ord_tbl_ent(dev, slot, -1);
+               ord = get_imsm_ord_tbl_ent(dev, slot, MAP_X);
                printf("      This Slot : %d%s\n", slot,
                       ord & IMSM_ORD_REBUILD ? " (out-of-sync)" : "");
        } else
@@ -1125,12 +1130,12 @@ static void print_imsm_dev(struct intel_super *super,
                printf("idle\n");
        printf("      Map State : %s", map_state_str[map->map_state]);
        if (dev->vol.migr_state) {
-               struct imsm_map *map = get_imsm_map(dev, 1);
+               struct imsm_map *map = get_imsm_map(dev, MAP_1);
 
                printf(" <-- %s", map_state_str[map->map_state]);
                printf("\n     Checkpoint : %u ",
                           __le32_to_cpu(dev->vol.curr_migr_unit));
-               if ((is_gen_migration(dev)) && (super->disks->index > 1))
+               if ((is_gen_migration(dev)) && ((slot > 1) || (slot < 0)))
                        printf("(N/A)");
                else
                        printf("(%llu)", (unsigned long long)
@@ -1171,11 +1176,19 @@ void examine_migr_rec_imsm(struct intel_super *super)
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct imsm_dev *dev = __get_imsm_dev(mpb, i);
+               struct imsm_map *map;
+               int slot = -1;
+
                if (is_gen_migration(dev) == 0)
                                continue;
 
                printf("\nMigration Record Information:");
-               if (super->disks->index > 1) {
+
+               /* first map under migration */
+               map = get_imsm_map(dev, MAP_0);
+               if (map)
+                       slot = get_imsm_disk_slot(map, super->disks->index);
+               if ((map == NULL) || (slot > 1) || (slot < 0)) {
                        printf(" Empty\n                              ");
                        printf("Examine one of first two disks in array\n");
                        break;
@@ -1860,7 +1873,7 @@ get_imsm_numerical_version(struct imsm_super *mpb, int *m, int *p)
 static __u32 migr_strip_blocks_resync(struct imsm_dev *dev)
 {
        /* migr_strip_size when repairing or initializing parity */
-       struct imsm_map *map = get_imsm_map(dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        __u32 chunk = __le32_to_cpu(map->blocks_per_strip);
 
        switch (get_imsm_raid_level(map)) {
@@ -1878,7 +1891,7 @@ static __u32 migr_strip_blocks_rebuild(struct imsm_dev *dev)
         * this is different than migr_strip_size_resync(), but it's good
         * to be compatible
         */
-       struct imsm_map *map = get_imsm_map(dev, 1);
+       struct imsm_map *map = get_imsm_map(dev, MAP_1);
        __u32 chunk = __le32_to_cpu(map->blocks_per_strip);
 
        switch (get_imsm_raid_level(map)) {
@@ -1897,8 +1910,8 @@ static __u32 migr_strip_blocks_rebuild(struct imsm_dev *dev)
 
 static __u32 num_stripes_per_unit_resync(struct imsm_dev *dev)
 {
-       struct imsm_map *lo = get_imsm_map(dev, 0);
-       struct imsm_map *hi = get_imsm_map(dev, 1);
+       struct imsm_map *lo = get_imsm_map(dev, MAP_0);
+       struct imsm_map *hi = get_imsm_map(dev, MAP_1);
        __u32 lo_chunk = __le32_to_cpu(lo->blocks_per_strip);
        __u32 hi_chunk = __le32_to_cpu(hi->blocks_per_strip);
 
@@ -1907,11 +1920,11 @@ static __u32 num_stripes_per_unit_resync(struct imsm_dev *dev)
 
 static __u32 num_stripes_per_unit_rebuild(struct imsm_dev *dev)
 {
-       struct imsm_map *lo = get_imsm_map(dev, 0);
+       struct imsm_map *lo = get_imsm_map(dev, MAP_0);
        int level = get_imsm_raid_level(lo);
 
        if (level == 1 || level == 10) {
-               struct imsm_map *hi = get_imsm_map(dev, 1);
+               struct imsm_map *hi = get_imsm_map(dev, MAP_1);
 
                return hi->num_domains;
        } else
@@ -1940,7 +1953,7 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map)
 
 static __u32 parity_segment_depth(struct imsm_dev *dev)
 {
-       struct imsm_map *map = get_imsm_map(dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        __u32 chunk =  __le32_to_cpu(map->blocks_per_strip);
 
        switch(get_imsm_raid_level(map)) {
@@ -1956,7 +1969,7 @@ static __u32 parity_segment_depth(struct imsm_dev *dev)
 
 static __u32 map_migr_block(struct imsm_dev *dev, __u32 block)
 {
-       struct imsm_map *map = get_imsm_map(dev, 1);
+       struct imsm_map *map = get_imsm_map(dev, MAP_1);
        __u32 chunk = __le32_to_cpu(map->blocks_per_strip);
        __u32 strip = block / chunk;
 
@@ -1995,7 +2008,7 @@ static __u64 blocks_per_migr_unit(struct intel_super *super,
        case MIGR_VERIFY:
        case MIGR_REPAIR:
        case MIGR_INIT: {
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map = get_imsm_map(dev, MAP_0);
                __u32 stripes_per_unit;
                __u32 blocks_per_unit;
                __u32 parity_depth;
@@ -2011,7 +2024,7 @@ static __u64 blocks_per_migr_unit(struct intel_super *super,
                 */
                stripes_per_unit = num_stripes_per_unit_resync(dev);
                migr_chunk = migr_strip_blocks_resync(dev);
-               disks = imsm_num_data_members(dev, 0);
+               disks = imsm_num_data_members(dev, MAP_0);
                blocks_per_unit = stripes_per_unit * migr_chunk * disks;
                stripe = __le16_to_cpu(map->blocks_per_strip) * disks;
                segment = blocks_per_unit / stripe;
@@ -2065,13 +2078,14 @@ static int read_imsm_migr_rec(int fd, struct intel_super *super)
        unsigned long long dsize;
 
        get_dev_size(fd, NULL, &dsize);
-       if (lseek64(fd, dsize - 512, SEEK_SET) < 0) {
+       if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
                fprintf(stderr,
                        Name ": Cannot seek to anchor block: %s\n",
                        strerror(errno));
                goto out;
        }
-       if (read(fd, super->migr_rec_buf, 512) != 512) {
+       if (read(fd, super->migr_rec_buf, MIGR_REC_BUF_SIZE) !=
+                                                           MIGR_REC_BUF_SIZE) {
                fprintf(stderr,
                        Name ": Cannot read migr record block: %s\n",
                        strerror(errno));
@@ -2083,6 +2097,19 @@ out:
        return ret_val;
 }
 
+static struct imsm_dev *imsm_get_device_during_migration(
+       struct intel_super *super)
+{
+
+       struct intel_dev *dv;
+
+       for (dv = super->devlist; dv; dv = dv->next) {
+               if (is_gen_migration(dv->dev))
+                       return dv->dev;
+       }
+       return NULL;
+}
+
 /*******************************************************************************
  * Function:   load_imsm_migr_rec
  * Description:        Function reads imsm migration record (it is stored at the last
@@ -2093,6 +2120,7 @@ out:
  * Returns:
  *      0 : success
  *     -1 : fail
+ *     -2 : no migration in progress
  ******************************************************************************/
 static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
 {
@@ -2101,13 +2129,31 @@ static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
        char nm[30];
        int retval = -1;
        int fd = -1;
+       struct imsm_dev *dev;
+       struct imsm_map *map = NULL;
+       int slot = -1;
+
+       /* find map under migration */
+       dev = imsm_get_device_during_migration(super);
+       /* nothing to load,no migration in progress?
+       */
+       if (dev == NULL)
+               return -2;
+       map = get_imsm_map(dev, MAP_0);
 
        if (info) {
                for (sd = info->devs ; sd ; sd = sd->next) {
+                       /* skip spare and failed disks
+                        */
+                       if (sd->disk.raid_disk < 0)
+                               continue;
                        /* read only from one of the first two slots */
-                       if ((sd->disk.raid_disk > 1) ||
-                           (sd->disk.raid_disk < 0))
+                       if (map)
+                               slot = get_imsm_disk_slot(map,
+                                                         sd->disk.raid_disk);
+                       if ((map == NULL) || (slot > 1) || (slot < 0))
                                continue;
+
                        sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
                        fd = dev_open(nm, O_RDONLY);
                        if (fd >= 0)
@@ -2116,8 +2162,14 @@ static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
        }
        if (fd < 0) {
                for (dl = super->disks; dl; dl = dl->next) {
+                       /* skip spare and failed disks
+                       */
+                       if (dl->index < 0)
+                               continue;
                        /* read only from one of the first two slots */
-                       if (dl->index > 1)
+                       if (map)
+                               slot = get_imsm_disk_slot(map, dl->index);
+                       if ((map == NULL) || (slot > 1) || (slot < 0))
                                continue;
                        sprintf(nm, "%d:%d", dl->major, dl->minor);
                        fd = dev_open(nm, O_RDONLY);
@@ -2201,23 +2253,45 @@ static int write_imsm_migr_rec(struct supertype *st)
        struct dl *sd;
        int len;
        struct imsm_update_general_migration_checkpoint *u;
+       struct imsm_dev *dev;
+       struct imsm_map *map = NULL;
+
+       /* find map under migration */
+       dev = imsm_get_device_during_migration(super);
+       /* if no migration, write buffer anyway to clear migr_record
+        * on disk based on first available device
+       */
+       if (dev == NULL)
+               dev = get_imsm_dev(super, super->current_vol < 0 ? 0 :
+                                         super->current_vol);
+
+       map = get_imsm_map(dev, MAP_0);
 
        for (sd = super->disks ; sd ; sd = sd->next) {
+               int slot = -1;
+
+               /* skip failed and spare devices */
+               if (sd->index < 0)
+                       continue;
                /* write to 2 first slots only */
-               if ((sd->index < 0) || (sd->index > 1))
+               if (map)
+                       slot = get_imsm_disk_slot(map, sd->index);
+               if ((map == NULL) || (slot > 1) || (slot < 0))
                        continue;
+
                sprintf(nm, "%d:%d", sd->major, sd->minor);
                fd = dev_open(nm, O_RDWR);
                if (fd < 0)
                        continue;
                get_dev_size(fd, NULL, &dsize);
-               if (lseek64(fd, dsize - 512, SEEK_SET) < 0) {
+               if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
                        fprintf(stderr,
                                Name ": Cannot seek to anchor block: %s\n",
                                strerror(errno));
                        goto out;
                }
-               if (write(fd, super->migr_rec_buf, 512) != 512) {
+               if (write(fd, super->migr_rec_buf, MIGR_REC_BUF_SIZE) !=
+                                                           MIGR_REC_BUF_SIZE) {
                        fprintf(stderr,
                                Name ": Cannot write migr record block: %s\n",
                                strerror(errno));
@@ -2284,8 +2358,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
        struct intel_super *super = st->sb;
        struct migr_record *migr_rec = super->migr_rec;
        struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
-       struct imsm_map *map = get_imsm_map(dev, 0);
-       struct imsm_map *prev_map = get_imsm_map(dev, 1);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
+       struct imsm_map *prev_map = get_imsm_map(dev, MAP_1);
        struct imsm_map *map_to_analyse = map;
        struct dl *dl;
        char *devname;
@@ -2430,7 +2504,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
                                (unsigned long long)blocks_per_unit,
                                info->reshape_progress);
 
-                       used_disks = imsm_num_data_members(dev, 1);
+                       used_disks = imsm_num_data_members(dev, MAP_1);
                        if (used_disks > 0) {
                                array_blocks = map->blocks_per_member *
                                        used_disks;
@@ -2475,7 +2549,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
                        dmap[i] = 0;
                        if (i < info->array.raid_disks) {
                                struct imsm_disk *dsk;
-                               j = get_imsm_disk_idx(dev, i, -1);
+                               j = get_imsm_disk_idx(dev, i, MAP_X);
                                dsk = get_imsm_disk(super, j);
                                if (dsk && (dsk->status & CONFIGURED_DISK))
                                        dmap[i] = 1;
@@ -2490,6 +2564,8 @@ static __u8 imsm_check_degraded(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);
 
+
+#ifndef MDASSEMBLE
 static void manage_second_map(struct intel_super *super, struct imsm_dev *dev)
 {
        if (is_gen_migration(dev)) {
@@ -2498,14 +2574,14 @@ static void manage_second_map(struct intel_super *super, struct imsm_dev *dev)
                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);
+               map_state = imsm_check_degraded(super, dev, failed, MAP_1);
                if (map2->map_state != map_state) {
                        map2->map_state = map_state;
                        super->updates_pending++;
                }
        }
 }
+#endif
 
 static struct imsm_disk *get_imsm_missing(struct intel_super *super, __u8 index)
 {
@@ -2568,13 +2644,13 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
 
                failed = imsm_count_failed(super, dev, MAP_0);
                state = imsm_check_degraded(super, dev, failed, MAP_0);
-               map = get_imsm_map(dev, 0);
+               map = get_imsm_map(dev, MAP_0);
 
                /* any newly missing disks?
                 * (catches single-degraded vs double-degraded)
                 */
                for (j = 0; j < map->num_members; j++) {
-                       __u32 ord = get_imsm_ord_tbl_ent(dev, j, 0);
+                       __u32 ord = get_imsm_ord_tbl_ent(dev, j, MAP_0);
                        __u32 idx = ord_to_idx(ord);
 
                        if (!(ord & IMSM_ORD_REBUILD) &&
@@ -2715,25 +2791,30 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info,
 
        mpb = super->anchor;
 
-       if (strcmp(update, "uuid") == 0 && uuid_set && !info->update_private)
-               rv = -1;
-       else if (strcmp(update, "uuid") == 0 && uuid_set && info->update_private) {
-               mpb->orig_family_num = *((__u32 *) info->update_private);
-               rv = 0;
-       } else if (strcmp(update, "uuid") == 0) {
-               __u32 *new_family = malloc(sizeof(*new_family));
-
-               /* update orig_family_number with the incoming random
-                * data, report the new effective uuid, and store the
-                * new orig_family_num for future updates.
+       if (strcmp(update, "uuid") == 0) {
+               /* We take this to mean that the family_num should be updated.
+                * However that is much smaller than the uuid so we cannot really
+                * allow an explicit uuid to be given.  And it is hard to reliably
+                * know if one was.
+                * So if !uuid_set we know the current uuid is random and just used
+                * the first 'int' and copy it to the other 3 positions.
+                * Otherwise we require the 4 'int's to be the same as would be the
+                * case if we are using a random uuid.  So an explicit uuid will be
+                * accepted as long as all for ints are the same... which shouldn't hurt
                 */
-               if (new_family) {
-                       memcpy(&mpb->orig_family_num, info->uuid, sizeof(__u32));
-                       uuid_from_super_imsm(st, info->uuid);
-                       *new_family = mpb->orig_family_num;
-                       info->update_private = new_family;
+               if (!uuid_set) {
+                       info->uuid[1] = info->uuid[2] = info->uuid[3] = info->uuid[0];
                        rv = 0;
+               } else {
+                       if (info->uuid[0] != info->uuid[1] ||
+                           info->uuid[1] != info->uuid[2] ||
+                           info->uuid[2] != info->uuid[3])
+                               rv = -1;
+                       else
+                               rv = 0;
                }
+               if (rv == 0)
+                       mpb->orig_family_num = info->uuid[0];
        } else if (strcmp(update, "assemble") == 0)
                rv = 0;
        else
@@ -3101,12 +3182,12 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super,
                    __u8 to_state, int migr_type)
 {
        struct imsm_map *dest;
-       struct imsm_map *src = get_imsm_map(dev, 0);
+       struct imsm_map *src = get_imsm_map(dev, MAP_0);
 
        dev->vol.migr_state = 1;
        set_migr_type(dev, migr_type);
        dev->vol.curr_migr_unit = 0;
-       dest = get_imsm_map(dev, 1);
+       dest = get_imsm_map(dev, MAP_1);
 
        /* duplicate and then set the target end state in map[0] */
        memcpy(dest, src, sizeof_imsm_map(src));
@@ -3131,8 +3212,9 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super,
 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);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
+       struct imsm_map *prev = get_imsm_map(dev, dev->vol.migr_state == 0 ?
+                                                   MAP_0 : MAP_1);
        int i, j;
 
        /* merge any IMSM_ORD_REBUILD bits that were not successfully
@@ -3264,8 +3346,8 @@ int check_mpb_migr_compatibility(struct intel_super *super)
                    dev_iter->vol.migr_state == 1 &&
                    dev_iter->vol.migr_type == MIGR_GEN_MIGR) {
                        /* This device is migrating */
-                       map0 = get_imsm_map(dev_iter, 0);
-                       map1 = get_imsm_map(dev_iter, 1);
+                       map0 = get_imsm_map(dev_iter, MAP_0);
+                       map1 = get_imsm_map(dev_iter, MAP_1);
                        if (map0->pba_of_lba0 != map1->pba_of_lba0)
                                /* migration optimization area was used */
                                return -1;
@@ -3351,7 +3433,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        sectors = mpb_sectors(anchor) - 1;
        free(anchor);
 
-       if (posix_memalign(&super->migr_rec_buf, 512, 512) != 0) {
+       if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
                fprintf(stderr, Name
                        ": %s could not allocate migr_rec buffer\n", __func__);
                free(super->buf);
@@ -4003,13 +4085,16 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
 
        /* load migration record */
        err = load_imsm_migr_rec(super, NULL);
-       if (err) {
+       if (err == -1) {
+               /* migration is in progress,
+                * but migr_rec cannot be loaded,
+                */
                err = 4;
                goto error;
        }
 
        /* Check migration compatibility */
-       if (check_mpb_migr_compatibility(super) != 0) {
+       if ((err == 0) && (check_mpb_migr_compatibility(super) != 0)) {
                fprintf(stderr, Name ": Unsupported migration detected");
                if (devname)
                        fprintf(stderr, " on %s\n", devname);
@@ -4152,7 +4237,7 @@ static void imsm_update_version_info(struct intel_super *super)
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                dev = get_imsm_dev(super, i);
-               map = get_imsm_map(dev, 0);
+               map = get_imsm_map(dev, MAP_0);
                if (__le32_to_cpu(dev->size_high) > 0)
                        mpb->attributes |= MPB_ATTRIB_2TB;
 
@@ -4248,7 +4333,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                        fprintf(stderr, Name": could not allocate new mpb\n");
                        return 0;
                }
-               if (posix_memalign(&super->migr_rec_buf, 512, 512) != 0) {
+               if (posix_memalign(&super->migr_rec_buf, 512,
+                                  MIGR_REC_BUF_SIZE) != 0) {
                        fprintf(stderr, Name
                                ": %s could not allocate migr_rec buffer\n",
                                __func__);
@@ -4332,7 +4418,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        set_migr_type(dev, MIGR_INIT);
        vol->dirty = !info->state;
        vol->curr_migr_unit = 0;
-       map = get_imsm_map(dev, 0);
+       map = get_imsm_map(dev, MAP_0);
        map->pba_of_lba0 = __cpu_to_le32(super->create_offset);
        map->blocks_per_member = __cpu_to_le32(info_to_blocks_per_member(info));
        map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
@@ -4416,7 +4502,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
                        ": %s could not allocate superblock\n", __func__);
                return 0;
        }
-       if (posix_memalign(&super->migr_rec_buf, 512, 512) != 0) {
+       if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
                fprintf(stderr, Name
                        ": %s could not allocate migr_rec buffer\n", __func__);
                free(super->buf);
@@ -4456,7 +4542,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        int slot;
 
        dev = get_imsm_dev(super, super->current_vol);
-       map = get_imsm_map(dev, 0);
+       map = get_imsm_map(dev, MAP_0);
 
        if (! (dk->state & (1<<MD_DISK_SYNC))) {
                fprintf(stderr, Name ": %s: Cannot add spare devices to IMSM volume\n",
@@ -4491,7 +4577,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        /* Check the device has not already been added */
        slot = get_imsm_disk_slot(map, dl->index);
        if (slot >= 0 &&
-           (get_imsm_ord_tbl_ent(dev, slot, -1) & IMSM_ORD_REBUILD) == 0) {
+           (get_imsm_ord_tbl_ent(dev, slot, MAP_X) & IMSM_ORD_REBUILD) == 0) {
                fprintf(stderr, Name ": %s has been included in this array twice\n",
                        devname);
                return 1;
@@ -4515,21 +4601,24 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        /* refresh unset/failed slots to point to valid 'missing' entries */
        for (df = super->missing; df; df = df->next)
                for (slot = 0; slot < mpb->num_disks; slot++) {
-                       __u32 ord = get_imsm_ord_tbl_ent(dev, slot, -1);
+                       __u32 ord = get_imsm_ord_tbl_ent(dev, slot, MAP_X);
 
                        if ((ord & IMSM_ORD_REBUILD) == 0)
                                continue;
                        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) {
+                               struct imsm_map *map2 = get_imsm_map(dev,
+                                                                    MAP_1);
+                               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,
-                                                                         1);
+                                                                        slot2,
+                                                                        MAP_1);
                                        if ((unsigned)df->index ==
                                                               ord_to_idx(ord2))
                                                set_imsm_ord_tbl_ent(map2,
-                                                       slot,
+                                                       slot2,
                                                        df->index |
                                                        IMSM_ORD_REBUILD);
                                }
@@ -4807,7 +4896,7 @@ static int write_super_imsm(struct supertype *st, int doclose)
        mpb->check_sum = __cpu_to_le32(sum);
 
        if (clear_migration_record)
-               memset(super->migr_rec_buf, 0, 512);
+               memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
 
        /* write the mpb for disks that compose raid devices */
        for (d = super->disks; d ; d = d->next) {
@@ -4821,7 +4910,8 @@ static int write_super_imsm(struct supertype *st, int doclose)
 
                        get_dev_size(d->fd, NULL, &dsize);
                        if (lseek64(d->fd, dsize - 512, SEEK_SET) >= 0) {
-                               if (write(d->fd, super->migr_rec_buf, 512) != 512)
+                               if (write(d->fd, super->migr_rec_buf,
+                                       MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
                                        perror("Write migr_rec failed");
                        }
                }
@@ -4844,7 +4934,7 @@ static int create_array(struct supertype *st, int dev_idx)
        struct imsm_update_create_array *u;
        struct intel_super *super = st->sb;
        struct imsm_dev *dev = get_imsm_dev(super, dev_idx);
-       struct imsm_map *map = get_imsm_map(dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        struct disk_info *inf;
        struct imsm_disk *disk;
        int i;
@@ -4863,7 +4953,7 @@ static int create_array(struct supertype *st, int dev_idx)
        imsm_copy_dev(&u->dev, dev);
        inf = get_disk_info(u);
        for (i = 0; i < map->num_members; i++) {
-               int idx = get_imsm_disk_idx(dev, i, -1);
+               int idx = get_imsm_disk_idx(dev, i, MAP_X);
 
                disk = get_imsm_disk(super, idx);
                serialcpy(inf[i].serial, disk->serial);
@@ -5224,12 +5314,6 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
 
        mpb = super->anchor;
 
-       if (mpb->num_raid_devs > 0 && mpb->num_disks != raiddisks) {
-               fprintf(stderr, Name ": the option-rom requires all "
-                       "member disks to be a member of all volumes.\n");
-               return 0;
-       }
-
        if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, verbose)) {
                fprintf(stderr, Name ": RAID gemetry validation failed. "
                        "Cannot proceed with the action(s).\n");
@@ -5308,6 +5392,11 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                fprintf(stderr, Name ": The option-rom requires all member"
                        " disks to be a member of all volumes\n");
                return 0;
+       } else if (super->orom && mpb->num_raid_devs > 0 &&
+                  mpb->num_disks != raiddisks) {
+               fprintf(stderr, Name ": The option-rom requires all member"
+                       " disks to be a member of all volumes\n");
+               return 0;
        }
 
        /* retrieve the largest free space block */
@@ -5356,9 +5445,16 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
        }
 
        if (maxsize < size || maxsize == 0) {
-               if (verbose)
-                       fprintf(stderr, Name ": not enough space after merge (%llu < %llu)\n",
-                               maxsize, size);
+               if (verbose) {
+                       if (maxsize == 0)
+                               fprintf(stderr, Name ": no free space"
+                                               " left on device. Aborting...\n");
+                       else
+                               fprintf(stderr, Name ": not enough space"
+                                               " to create volume of given size"
+                                               " (%llu < %llu). Aborting...\n",
+                                               maxsize, size);
+               }
                return 0;
        }
 
@@ -5710,7 +5806,7 @@ static int is_rebuilding(struct imsm_dev *dev)
        if (migr_type(dev) != MIGR_REBUILD)
                return 0;
 
-       migr_map = get_imsm_map(dev, 1);
+       migr_map = get_imsm_map(dev, MAP_1);
 
        if (migr_map->map_state == IMSM_T_STATE_DEGRADED)
                return 1;
@@ -5718,6 +5814,7 @@ static int is_rebuilding(struct imsm_dev *dev)
                return 0;
 }
 
+#ifndef MDASSEMBLE
 static int is_initializing(struct imsm_dev *dev)
 {
        struct imsm_map *migr_map;
@@ -5728,14 +5825,14 @@ static int is_initializing(struct imsm_dev *dev)
        if (migr_type(dev) != MIGR_INIT)
                return 0;
 
-       migr_map = get_imsm_map(dev, 1);
+       migr_map = get_imsm_map(dev, MAP_1);
 
        if (migr_map->map_state == IMSM_T_STATE_UNINITIALIZED)
                return 1;
 
        return 0;
-
 }
+#endif
 
 static void update_recovery_start(struct intel_super *super,
                                        struct imsm_dev *dev,
@@ -5818,7 +5915,10 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                struct imsm_map *map;
                struct imsm_map *map2;
                struct mdinfo *this;
-               int slot, chunk;
+               int slot;
+#ifndef MDASSEMBLE
+               int chunk;
+#endif
                char *ep;
 
                if (subarray &&
@@ -5826,8 +5926,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                        continue;
 
                dev = get_imsm_dev(super, i);
-               map = get_imsm_map(dev, 0);
-               map2 = get_imsm_map(dev, 1);
+               map = get_imsm_map(dev, MAP_0);
+               map2 = get_imsm_map(dev, MAP_1);
 
                /* do not publish arrays that are in the middle of an
                 * unsupported migration
@@ -5843,7 +5943,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                 * OROM/EFI
                 */
 
-               chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
                this = malloc(sizeof(*this));
                if (!this) {
                        fprintf(stderr, Name ": failed to allocate %zu bytes\n",
@@ -5855,6 +5954,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                getinfo_super_imsm_volume(st, this, NULL);
                this->next = rest;
 #ifndef MDASSEMBLE
+               chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
                /* mdadm does not support all metadata features- set the bit in all arrays state */
                if (!validate_geometry_imsm_orom(super,
                                                 get_imsm_raid_level(map), /* RAID level */
@@ -5886,8 +5986,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                        __u32 ord;
 
                        skip = 0;
-                       idx = get_imsm_disk_idx(dev, slot, 0);
-                       ord = get_imsm_ord_tbl_ent(dev, slot, -1);
+                       idx = get_imsm_disk_idx(dev, slot, MAP_0);
+                       ord = get_imsm_ord_tbl_ent(dev, slot, MAP_X);
                        for (d = super->disks; d ; d = d->next)
                                if (d->index == idx)
                                        break;
@@ -6002,7 +6102,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
                int insync = insync;
 
                for (i = 0; i < map->num_members; i++) {
-                       __u32 ord = get_imsm_ord_tbl_ent(dev, i, -1);
+                       __u32 ord = get_imsm_ord_tbl_ent(dev, i, MAP_X);
                        int idx = ord_to_idx(ord);
                        struct imsm_disk *disk;
 
@@ -6063,8 +6163,11 @@ static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev,
 
        for (i = 0; i < map_for_loop->num_members; i++) {
                idx_1 = -255;
+               /* when MAP_X is passed both maps failures are counted
+                */
                if (prev &&
-                   (look_in_map & MAP_1) && (i < prev->num_members)) {
+                   ((look_in_map == MAP_1) || (look_in_map == MAP_X)) &&
+                   (i < prev->num_members)) {
                        ord = __le32_to_cpu(prev->disk_ord_tbl[i]);
                        idx_1 = ord_to_idx(ord);
 
@@ -6072,7 +6175,8 @@ static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev,
                        if (!disk || is_failed(disk) || ord & IMSM_ORD_REBUILD)
                                failed++;
                }
-               if ((look_in_map & MAP_0) && (i < map->num_members)) {
+               if (((look_in_map == MAP_0) || (look_in_map == MAP_X)) &&
+                   (i < map->num_members)) {
                        ord = __le32_to_cpu(map->disk_ord_tbl[i]);
                        idx = ord_to_idx(ord);
 
@@ -6120,7 +6224,7 @@ static int is_resyncing(struct imsm_dev *dev)
        if (migr_type(dev) == MIGR_GEN_MIGR)
                return 0;
 
-       migr_map = get_imsm_map(dev, 1);
+       migr_map = get_imsm_map(dev, MAP_1);
 
        if ((migr_map->map_state == IMSM_T_STATE_NORMAL) &&
            (dev->vol.migr_type != MIGR_GEN_MIGR))
@@ -6139,7 +6243,7 @@ static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
        unsigned int len, shift = 0;
 
        /* new failures are always set in map[0] */
-       map = get_imsm_map(dev, 0);
+       map = get_imsm_map(dev, MAP_0);
 
        slot = get_imsm_disk_slot(map, idx);
        if (slot < 0)
@@ -6158,10 +6262,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)) {
-               struct imsm_map *map2 = get_imsm_map(dev, 1);
-               if (slot < map2->num_members)
-                       set_imsm_ord_tbl_ent(map2, slot,
+       /* 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, MAP_1);
+               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)
@@ -6188,6 +6299,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++;
@@ -6195,7 +6317,7 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
 
 static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
 {
-       int used_disks = imsm_num_data_members(dev, 0);
+       int used_disks = imsm_num_data_members(dev, MAP_0);
        unsigned long long array_blocks;
        struct imsm_map *map;
 
@@ -6212,7 +6334,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
 
        /* set array size in metadata
         */
-       map = get_imsm_map(dev, 0);
+       map = get_imsm_map(dev, MAP_0);
        array_blocks = map->blocks_per_member * used_disks;
 
        /* round array size down to closest MB
@@ -6240,7 +6362,7 @@ static void imsm_progress_container_reshape(struct intel_super *super)
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map = get_imsm_map(dev, MAP_0);
                struct imsm_map *map2;
                int prev_num_members;
 
@@ -6265,7 +6387,7 @@ static void imsm_progress_container_reshape(struct intel_super *super)
                for (i = prev_num_members;
                     i < map->num_members; i++)
                        set_imsm_ord_tbl_ent(map, i, i);
-               map2 = get_imsm_map(dev, 1);
+               map2 = get_imsm_map(dev, MAP_1);
                /* Copy the current map */
                memcpy(map2, map, copy_map_size);
                map2->num_members = prev_num_members;
@@ -6285,7 +6407,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
        int inst = a->info.container_member;
        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);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        int failed = imsm_count_failed(super, dev, MAP_0);
        __u8 map_state = imsm_check_degraded(super, dev, failed, MAP_0);
        __u32 blocks_per_unit;
@@ -6309,12 +6431,14 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                                 * user action is required to recover process
                                 */
                                if (0) {
-                               struct imsm_map *map2 = get_imsm_map(dev, 1);
-                               dev->vol.migr_state = 0;
-                               set_migr_type(dev, 0);
-                               dev->vol.curr_migr_unit = 0;
-                               memcpy(map, map2, sizeof_imsm_map(map2));
-                               super->updates_pending++;
+                                       struct imsm_map *map2 =
+                                               get_imsm_map(dev, MAP_1);
+                                       dev->vol.migr_state = 0;
+                                       set_migr_type(dev, 0);
+                                       dev->vol.curr_migr_unit = 0;
+                                       memcpy(map, map2,
+                                              sizeof_imsm_map(map2));
+                                       super->updates_pending++;
                                }
                        }
                        if (a->last_checkpoint >= a->info.component_size) {
@@ -6322,7 +6446,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                                int used_disks;
                                struct mdinfo *mdi;
 
-                               used_disks = imsm_num_data_members(dev, 0);
+                               used_disks = imsm_num_data_members(dev, MAP_0);
                                if (used_disks > 0) {
                                        array_blocks =
                                                map->blocks_per_member *
@@ -6429,7 +6553,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
        int inst = a->info.container_member;
        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);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        struct imsm_disk *disk;
        int failed;
        __u32 ord;
@@ -6444,7 +6568,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
 
        dprintf("imsm: set_disk %d:%x\n", n, state);
 
-       ord = get_imsm_ord_tbl_ent(dev, n, 0);
+       ord = get_imsm_ord_tbl_ent(dev, n, MAP_0);
        disk = get_imsm_disk(super, ord_to_idx(ord));
 
        /* check for new failures */
@@ -6455,7 +6579,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
 
        /* check if in_sync */
        if (state & DS_INSYNC && ord & IMSM_ORD_REBUILD && is_rebuilding(dev)) {
-               struct imsm_map *migr_map = get_imsm_map(dev, 1);
+               struct imsm_map *migr_map = get_imsm_map(dev, MAP_1);
 
                set_imsm_ord_tbl_ent(migr_map, n, ord_to_idx(ord));
                super->updates_pending++;
@@ -6472,7 +6596,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                if (is_rebuilding(dev)) {
                        dprintf("while rebuilding");
                        end_migration(dev, super, map_state);
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
                        map->failed_disk_num = ~0;
                        super->updates_pending++;
                        a->last_checkpoint = 0;
@@ -6484,7 +6608,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                                end_migration(dev, super, map_state);
                        else
                                map->map_state = map_state;
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
                        map->failed_disk_num = ~0;
                        super->updates_pending++;
                        break;
@@ -6598,7 +6722,7 @@ static void imsm_sync_metadata(struct supertype *container)
 static struct dl *imsm_readd(struct intel_super *super, int idx, struct active_array *a)
 {
        struct imsm_dev *dev = get_imsm_dev(super, a->info.container_member);
-       int i = get_imsm_disk_idx(dev, idx, -1);
+       int i = get_imsm_disk_idx(dev, idx, MAP_X);
        struct dl *dl;
 
        for (dl = super->disks; dl; dl = dl->next)
@@ -6619,7 +6743,7 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot,
                                 struct mdinfo *additional_test_list)
 {
        struct imsm_dev *dev = get_imsm_dev(super, a->info.container_member);
-       int idx = get_imsm_disk_idx(dev, slot, -1);
+       int idx = get_imsm_disk_idx(dev, slot, MAP_X);
        struct imsm_super *mpb = super->anchor;
        struct imsm_map *map;
        unsigned long long pos;
@@ -6681,7 +6805,7 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot,
                }
                for (i = 0; i < mpb->num_raid_devs; i++) {
                        dev = get_imsm_dev(super, i);
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
 
                        /* check if this disk is already a member of
                         * this array
@@ -6737,10 +6861,9 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
 
        dev2 = get_imsm_dev(cont->sb, dev_idx);
        if (dev2) {
-               state = imsm_check_degraded(cont->sb, dev2, failed,
-                                           MAP_0);
+               state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
                if (state == IMSM_T_STATE_FAILED) {
-                       map = get_imsm_map(dev2, 0);
+                       map = get_imsm_map(dev2, MAP_0);
                        if (!map)
                                return 1;
                        for (slot = 0; slot < map->num_members; slot++) {
@@ -6748,7 +6871,7 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
                                 * Check if failed disks are deleted from intel
                                 * disk list or are marked to be deleted
                                 */
-                               idx = get_imsm_disk_idx(dev2, slot, -1);
+                               idx = get_imsm_disk_idx(dev2, slot, MAP_X);
                                idisk = get_imsm_dl_disk(cont->sb, idx);
                                /*
                                 * Do not rebuild the array if failed disks
@@ -6782,7 +6905,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
        struct intel_super *super = a->container->sb;
        int inst = a->info.container_member;
        struct imsm_dev *dev = get_imsm_dev(super, inst);
-       struct imsm_map *map = get_imsm_map(dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        int failed = a->info.array.raid_disks;
        struct mdinfo *rv = NULL;
        struct mdinfo *d;
@@ -6955,15 +7078,15 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
 static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_create_array *u)
 {
        struct imsm_dev *dev = get_imsm_dev(super, idx);
-       struct imsm_map *map = get_imsm_map(dev, 0);
-       struct imsm_map *new_map = get_imsm_map(&u->dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
+       struct imsm_map *new_map = get_imsm_map(&u->dev, MAP_0);
        struct disk_info *inf = get_disk_info(u);
        struct imsm_disk *disk;
        int i;
        int j;
 
        for (i = 0; i < map->num_members; i++) {
-               disk = get_imsm_disk(super, get_imsm_disk_idx(dev, i, -1));
+               disk = get_imsm_disk(super, get_imsm_disk_idx(dev, i, MAP_X));
                for (j = 0; j < new_map->num_members; j++)
                        if (serialcmp(disk->serial, inf[j].serial) == 0)
                                return 1;
@@ -7076,7 +7199,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
                        struct imsm_map *map;
                        struct imsm_dev *new_dev =
                                (struct imsm_dev *)*space_list;
-                       struct imsm_map *migr_map = get_imsm_map(dev, 1);
+                       struct imsm_map *migr_map = get_imsm_map(dev, MAP_1);
                        int to_state;
                        struct dl *new_disk;
 
@@ -7084,7 +7207,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
                                return ret_val;
                        *space_list = **space_list;
                        memcpy(new_dev, dev, sizeof_imsm_dev(dev, 0));
-                       map = get_imsm_map(new_dev, 0);
+                       map = get_imsm_map(new_dev, MAP_0);
                        if (migr_map) {
                                dprintf("imsm: Error: migration in progress");
                                return ret_val;
@@ -7104,7 +7227,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
                        migrate(new_dev, super, to_state, MIGR_GEN_MIGR);
                        if (u->new_level > -1)
                                map->raid_level = u->new_level;
-                       migr_map = get_imsm_map(new_dev, 1);
+                       migr_map = get_imsm_map(new_dev, MAP_1);
                        if ((u->new_level == 5) &&
                            (migr_map->raid_level == 0)) {
                                int ord = map->num_members - 1;
@@ -7179,7 +7302,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
 {
        struct imsm_super *mpb = super->anchor;
        struct imsm_dev *dev = get_imsm_dev(super, u->array);
-       struct imsm_map *map = get_imsm_map(dev, 0);
+       struct imsm_map *map = get_imsm_map(dev, MAP_0);
        struct imsm_map *migr_map;
        struct active_array *a;
        struct imsm_disk *disk;
@@ -7192,7 +7315,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
        int second_map_created = 0;
 
        for (; u; u = u->next) {
-               victim = get_imsm_disk_idx(dev, u->slot, -1);
+               victim = get_imsm_disk_idx(dev, u->slot, MAP_X);
 
                if (victim < 0)
                        return 0;
@@ -7216,7 +7339,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
                        if (i == u->slot)
                                continue;
                        disk = get_imsm_disk(super,
-                                            get_imsm_disk_idx(dev, i, -1));
+                                            get_imsm_disk_idx(dev, i, MAP_X));
                        if (!disk || is_failed(disk))
                                failed++;
                }
@@ -7231,15 +7354,14 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
                disk->status &= ~SPARE_DISK;
 
                /* mark rebuild */
-               to_state = imsm_check_degraded(super, dev, failed,
-                                              MAP_0);
+               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;
                        migrate(dev, super, to_state, MIGR_REBUILD);
                } else
                        map->map_state = to_state;
-               migr_map = get_imsm_map(dev, 1);
+               migr_map = get_imsm_map(dev, MAP_1);
                set_imsm_ord_tbl_ent(map, u->slot, dl->index);
                set_imsm_ord_tbl_ent(migr_map, u->slot,
                                     dl->index | IMSM_ORD_REBUILD);
@@ -7257,7 +7379,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
                found = 0;
                for (a = active_array; a ; a = a->next) {
                        dev = get_imsm_dev(super, a->info.container_member);
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
 
                        if (get_imsm_disk_slot(map, victim) >= 0)
                                found++;
@@ -7349,8 +7471,8 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
                newdev = (void*)sp;
                /* Copy the dev, but not (all of) the map */
                memcpy(newdev, id->dev, sizeof(*newdev));
-               oldmap = get_imsm_map(id->dev, 0);
-               newmap = get_imsm_map(newdev, 0);
+               oldmap = get_imsm_map(id->dev, MAP_0);
+               newmap = get_imsm_map(newdev, MAP_0);
                /* Copy the current map */
                memcpy(newmap, oldmap, sizeof_imsm_map(oldmap));
                /* update one device only
@@ -7370,7 +7492,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
                        }
                        /* New map is correct, now need to save old map
                         */
-                       newmap = get_imsm_map(newdev, 1);
+                       newmap = get_imsm_map(newdev, MAP_1);
                        memcpy(newmap, oldmap, sizeof_imsm_map(oldmap));
 
                        imsm_set_array_size(newdev);
@@ -7413,7 +7535,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
        if (dev == NULL)
                return 0;
 
-       map = get_imsm_map(dev, 0);
+       map = get_imsm_map(dev, MAP_0);
 
        if (u->direction == R10_TO_R0) {
                /* Number of failed disks must be half of initial disk number */
@@ -7477,7 +7599,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
                dev_new = (void *)space;
                memcpy(dev_new, dev, sizeof(*dev));
                /* update new map */
-               map = get_imsm_map(dev_new, 0);
+               map = get_imsm_map(dev_new, MAP_0);
                map->num_members = map->num_members * 2;
                map->map_state = IMSM_T_STATE_DEGRADED;
                map->num_domains = 2;
@@ -7621,7 +7743,7 @@ static void imsm_process_update(struct supertype *st,
                        goto create_error;
                }
 
-               new_map = get_imsm_map(&u->dev, 0);
+               new_map = get_imsm_map(&u->dev, MAP_0);
                new_start = __le32_to_cpu(new_map->pba_of_lba0);
                new_end = new_start + __le32_to_cpu(new_map->blocks_per_member);
                inf = get_disk_info(u);
@@ -7632,7 +7754,7 @@ static void imsm_process_update(struct supertype *st,
                 */
                for (i = 0; i < mpb->num_raid_devs; i++) {
                        dev = get_imsm_dev(super, i);
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
                        start = __le32_to_cpu(map->pba_of_lba0);
                        end = start + __le32_to_cpu(map->blocks_per_member);
                        if ((new_start >= start && new_start <= end) ||
@@ -7813,7 +7935,7 @@ static void imsm_prepare_update(struct supertype *st,
                if (u->direction == R0_TO_R10) {
                        void **tail = (void **)&update->space_list;
                        struct imsm_dev *dev = get_imsm_dev(super, u->subarray);
-                       struct imsm_map *map = get_imsm_map(dev, 0);
+                       struct imsm_map *map = get_imsm_map(dev, MAP_0);
                        int num_members = map->num_members;
                        void *space;
                        int size, i;
@@ -7945,7 +8067,7 @@ static void imsm_prepare_update(struct supertype *st,
                                struct imsm_map *map;
 
                                dev = get_imsm_dev(super, u->subdev);
-                               map = get_imsm_map(dev, 0);
+                               map = get_imsm_map(dev, MAP_0);
                                current_level = map->raid_level;
                                break;
                        }
@@ -7979,7 +8101,7 @@ static void imsm_prepare_update(struct supertype *st,
                struct imsm_update_create_array *u = (void *) update->buf;
                struct intel_dev *dv;
                struct imsm_dev *dev = &u->dev;
-               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map = get_imsm_map(dev, MAP_0);
                struct dl *dl;
                struct disk_info *inf;
                int i;
@@ -8064,20 +8186,20 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                dev = get_imsm_dev(super, i);
-               map = get_imsm_map(dev, 0);
+               map = get_imsm_map(dev, MAP_0);
                num_members = map->num_members;
                for (j = 0; j < num_members; j++) {
                        /* update ord entries being careful not to propagate
                         * ord-flags to the first map
                         */
-                       ord = get_imsm_ord_tbl_ent(dev, j, -1);
+                       ord = get_imsm_ord_tbl_ent(dev, j, MAP_X);
 
                        if (ord_to_idx(ord) <= index)
                                continue;
 
-                       map = get_imsm_map(dev, 0);
+                       map = get_imsm_map(dev, MAP_0);
                        set_imsm_ord_tbl_ent(map, j, ord_to_idx(ord - 1));
-                       map = get_imsm_map(dev, 1);
+                       map = get_imsm_map(dev, MAP_1);
                        if (map)
                                set_imsm_ord_tbl_ent(map, j, ord - 1);
                }
@@ -8123,7 +8245,7 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
                /* check map if all disks pairs not failed
                 * in both maps
                 */
-               map = get_imsm_map(dev, 0);
+               map = get_imsm_map(dev, MAP_0);
                for (i = 0; i < ret_val; i++) {
                        int degradation = 0;
                        if (get_imsm_disk(super, i) == NULL)
@@ -8133,7 +8255,7 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
                        if (degradation == 2)
                                return 0;
                }
-               map = get_imsm_map(dev, 1);
+               map = get_imsm_map(dev, MAP_1);
                /* if there is no second map
                 * result can be returned
                 */
@@ -8242,8 +8364,8 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
        struct mdinfo *sd;
        char nm[30];
        int fd;
-       struct imsm_map *map_dest = get_imsm_map(dev, 0);
-       struct imsm_map *map_src = get_imsm_map(dev, 1);
+       struct imsm_map *map_dest = get_imsm_map(dev, MAP_0);
+       struct imsm_map *map_src = get_imsm_map(dev, MAP_1);
        unsigned long long num_migr_units;
        unsigned long long array_blocks;
 
@@ -8256,7 +8378,7 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
        migr_rec->dest_depth_per_unit = GEN_MIGR_AREA_SIZE /
                max(map_dest->blocks_per_strip, map_src->blocks_per_strip);
        migr_rec->dest_depth_per_unit *= map_dest->blocks_per_strip;
-       new_data_disks = imsm_num_data_members(dev, 0);
+       new_data_disks = imsm_num_data_members(dev, MAP_0);
        migr_rec->blocks_per_unit =
                __cpu_to_le32(migr_rec->dest_depth_per_unit * new_data_disks);
        migr_rec->dest_depth_per_unit =
@@ -8320,12 +8442,12 @@ int save_backup_imsm(struct supertype *st,
        unsigned long long *target_offsets = NULL;
        int *targets = NULL;
        int i;
-       struct imsm_map *map_dest = get_imsm_map(dev, 0);
+       struct imsm_map *map_dest = get_imsm_map(dev, MAP_0);
        int new_disks = map_dest->num_members;
        int dest_layout = 0;
        int dest_chunk;
        unsigned long long start;
-       int data_disks = imsm_num_data_members(dev, 0);
+       int data_disks = imsm_num_data_members(dev, MAP_0);
 
        targets = malloc(new_disks * sizeof(int));
        if (!targets)
@@ -8485,7 +8607,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
        if (id == NULL)
                return 1;
 
-       map_dest = get_imsm_map(id->dev, 0);
+       map_dest = get_imsm_map(id->dev, MAP_0);
        new_disks = map_dest->num_members;
 
        read_offset = (unsigned long long)
@@ -8870,7 +8992,7 @@ static int imsm_create_metadata_update_for_migration(
        if (dev) {
                struct imsm_map *map;
 
-               map = get_imsm_map(dev, 0);
+               map = get_imsm_map(dev, MAP_0);
                if (map) {
                        int current_chunk_size =
                                __le16_to_cpu(map->blocks_per_strip) / 2;
@@ -8939,8 +9061,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
        int change = -1;
        int check_devs = 0;
        int chunk;
-       int devNumChange=0;
-       int layout = -1;
+       /* number of added/removed disks in operation result */
+       int devNumChange = 0;
+       /* imsm compatible layout value for array geometry verification */
+       int imsm_layout = -1;
 
        getinfo_super_imsm_volume(st, &info, NULL);
        if ((geo->level != info.array.level) &&
@@ -8958,14 +9082,14 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                                        change = -1;
                                        goto analyse_change_exit;
                                }
-                               layout =  geo->layout;
+                               imsm_layout =  geo->layout;
                                check_devs = 1;
                                devNumChange = 1; /* parity disk added */
                        } else if (geo->level == 10) {
                                change = CH_TAKEOVER;
                                check_devs = 1;
                                devNumChange = 2; /* two mirrors added */
-                               layout = 0x102; /* imsm supported layout */
+                               imsm_layout = 0x102; /* imsm supported layout */
                        }
                        break;
                case 1:
@@ -8974,7 +9098,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                                change = CH_TAKEOVER;
                                check_devs = 1;
                                devNumChange = -(geo->raid_disks/2);
-                               layout = 0; /* imsm raid0 layout */
+                               imsm_layout = 0; /* imsm raid0 layout */
                        }
                        break;
                }
@@ -9009,8 +9133,11 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        change = -1;
                        goto analyse_change_exit;
                }
-       } else
+       } else {
                geo->layout = info.array.layout;
+               if (imsm_layout == -1)
+                       imsm_layout = info.array.layout;
+       }
 
        if ((geo->chunksize > 0) && (geo->chunksize != UnSet)
            && (geo->chunksize != info.array.chunk_size))
@@ -9021,7 +9148,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
        chunk = geo->chunksize / 1024;
        if (!validate_geometry_imsm(st,
                                    geo->level,
-                                   layout,
+                                   imsm_layout,
                                    geo->raid_disks + devNumChange,
                                    &chunk,
                                    geo->size,
@@ -9382,12 +9509,12 @@ static int imsm_manage_reshape(
                goto abort;
        }
 
-       map_src = get_imsm_map(dev, 1);
+       map_src = get_imsm_map(dev, MAP_1);
        if (map_src == NULL)
                goto abort;
 
-       ndata = imsm_num_data_members(dev, 0);
-       odata = imsm_num_data_members(dev, 1);
+       ndata = imsm_num_data_members(dev, MAP_0);
+       odata = imsm_num_data_members(dev, MAP_1);
 
        chunk = __le16_to_cpu(map_src->blocks_per_strip) * 512;
        old_data_stripe_length = odata * chunk;