]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
Consistently print program Name and __func__ in debug messages.
[thirdparty/mdadm.git] / super-intel.c
index baea13cc3a8170158039f3701ea770eb30a5bb00..b400fded45c393ccd7093121c28bc7b1a5fbca27 100644 (file)
@@ -509,7 +509,8 @@ struct imsm_update_add_remove_disk {
 static const char *_sys_dev_type[] = {
        [SYS_DEV_UNKNOWN] = "Unknown",
        [SYS_DEV_SAS] = "SAS",
-       [SYS_DEV_SATA] = "SATA"
+       [SYS_DEV_SATA] = "SATA",
+       [SYS_DEV_NVME] = "NVMe"
 };
 
 const char *get_sys_dev_type(enum sys_dev_type type)
@@ -555,11 +556,26 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device
        if (super->hba == NULL) {
                super->hba = alloc_intel_hba(device);
                return 1;
-       } else
-               /* IMSM metadata disallows to attach disks to multiple
-                * controllers.
-                */
+       }
+
+       hba = super->hba;
+       /* Intel metadata allows for all disks attached to the same type HBA.
+        * Do not support HBA types mixing
+        */
+       if (device->type != hba->type)
                return 2;
+
+       /* Multiple same type HBAs can be used if they share the same OROM */
+       const struct imsm_orom *device_orom = get_orom_by_device_id(device->dev_id);
+
+       if (device_orom != super->orom)
+               return 2;
+
+       while (hba->next)
+               hba = hba->next;
+
+       hba->next = alloc_intel_hba(device);
+       return 1;
 }
 
 static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
@@ -1370,7 +1386,7 @@ static int imsm_check_attributes(__u32 attributes)
                }
 
                if (not_supported)
-                       dprintf(Name "(IMSM): Unknown attributes : %x\n", not_supported);
+                       dprintf("(IMSM): Unknown attributes : %x\n", not_supported);
 
                ret_val = 0;
        }
@@ -1693,7 +1709,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
                        break;
                }
                *c = '\0';
-               if (sscanf(&path[hba_len], "host%d", &port) == 1)
+               if ((sscanf(&path[hba_len], "ata%d", &port) == 1) ||
+                  ((sscanf(&path[hba_len], "host%d", &port) == 1)))
                        port -= host_base;
                else {
                        if (verbose > 0) {
@@ -1752,6 +1769,8 @@ static void print_found_intel_controllers(struct sys_dev *elem)
                        fprintf(stderr, "SATA ");
                else if (elem->type == SYS_DEV_SAS)
                        fprintf(stderr, "SAS ");
+               else if (elem->type == SYS_DEV_NVME)
+                       fprintf(stderr, "NVMe ");
                fprintf(stderr, "RAID controller");
                if (elem->pci_id)
                        fprintf(stderr, " at %s", elem->pci_id);
@@ -1773,7 +1792,8 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
        for (ent = readdir(dir); ent; ent = readdir(dir)) {
                int host;
 
-               if (sscanf(ent->d_name, "host%d", &host) != 1)
+               if ((sscanf(ent->d_name, "ata%d", &host) != 1) &&
+                  ((sscanf(ent->d_name, "host%d", &host) != 1)))
                        continue;
                if (*port_count == 0)
                        host_base = host;
@@ -1789,9 +1809,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
 
 static void print_imsm_capability(const struct imsm_orom *orom)
 {
-       printf("       Platform : Intel(R) Matrix Storage Manager\n");
-       printf("        Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
-              orom->hotfix_ver, orom->build);
+       printf("       Platform : Intel(R) ");
+       if (orom->capabilities == 0 && orom->driver_features == 0)
+               printf("Matrix Storage Manager\n");
+       else
+               printf("Rapid Storage Technology%s\n",
+                       imsm_orom_is_enterprise(orom) ? " enterprise" : "");
+       if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
+               printf("        Version : %d.%d.%d.%d\n", orom->major_ver,
+                               orom->minor_ver, orom->hotfix_ver, orom->build);
        printf("    RAID Levels :%s%s%s%s%s\n",
               imsm_orom_has_raid0(orom) ? " raid0" : "",
               imsm_orom_has_raid1(orom) ? " raid1" : "",
@@ -1820,16 +1846,18 @@ static void print_imsm_capability(const struct imsm_orom *orom)
        printf("      2TB disks :%s supported\n",
               (orom->attr & IMSM_OROM_ATTR_2TB_DISK)?"":" not");
        printf("      Max Disks : %d\n", orom->tds);
-       printf("    Max Volumes : %d per array, %d per controller\n",
-              orom->vpa, orom->vphba);
+       printf("    Max Volumes : %d per array, %d per %s\n",
+              orom->vpa, orom->vphba,
+              imsm_orom_is_nvme(orom) ? "platform" : "controller");
        return;
 }
 
 static void print_imsm_capability_export(const struct imsm_orom *orom)
 {
        printf("MD_FIRMWARE_TYPE=imsm\n");
-       printf("IMSM_VERSION=%d.%d.%d.%d\n",orom->major_ver, orom->minor_ver,
-                       orom->hotfix_ver, orom->build);
+       if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
+               printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
+                               orom->hotfix_ver, orom->build);
        printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
                        imsm_orom_has_raid0(orom) ? "raid0 " : "",
                        imsm_orom_has_raid1(orom) ? "raid1 " : "",
@@ -1873,7 +1901,6 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
         * platform capabilities.  If raid support is disabled in the BIOS the
         * option-rom capability structure will not be available.
         */
-       const struct imsm_orom *orom;
        struct sys_dev *list, *hba;
        int host_base = 0;
        int port_count = 0;
@@ -1886,13 +1913,12 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                if (!list)
                        return 2;
                for (hba = list; hba; hba = hba->next) {
-                       orom = find_imsm_capability(hba->type);
-                       if (!orom) {
-                               result = 2;
+                       if (find_imsm_capability(hba)) {
+                               result = 0;
                                break;
                        }
                        else
-                               result = 0;
+                               result = 2;
                }
                return result;
        }
@@ -1907,15 +1933,42 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                print_found_intel_controllers(list);
 
        for (hba = list; hba; hba = hba->next) {
-               if (controller_path && (compare_paths(hba->path,controller_path) != 0))
+               if (controller_path && (compare_paths(hba->path, controller_path) != 0))
                        continue;
-               orom = find_imsm_capability(hba->type);
-               if (!orom)
+               if (!find_imsm_capability(hba)) {
                        pr_err("imsm capabilities not found for controller: %s (type %s)\n",
                                hba->path, get_sys_dev_type(hba->type));
-               else {
-                       result = 0;
-                       print_imsm_capability(orom);
+                       continue;
+               }
+               result = 0;
+       }
+
+       if (controller_path && result == 1) {
+               pr_err("no active Intel(R) RAID controller found under %s\n",
+                               controller_path);
+               return result;
+       }
+
+       const struct orom_entry *oroms = get_oroms();
+       int i;
+
+       for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++) {
+               print_imsm_capability(&oroms[i].orom);
+
+               if (imsm_orom_is_nvme(&oroms[i].orom)) {
+                       for (hba = list; hba; hba = hba->next) {
+                               if (hba->type == SYS_DEV_NVME)
+                                       printf("    NVMe Device : %s\n", hba->path);
+                       }
+                       continue;
+               }
+
+               struct devid_list *devid;
+               for (devid = oroms[i].devid_list; devid; devid = devid->next) {
+                       hba = device_by_id(devid->devid);
+                       if (!hba)
+                               continue;
+
                        printf(" I/O Controller : %s (%s)\n",
                                hba->path, get_sys_dev_type(hba->type));
                        if (hba->type == SYS_DEV_SATA) {
@@ -1928,18 +1981,14 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                                }
                        }
                }
+               printf("\n");
        }
 
-       if (controller_path && result == 1)
-               pr_err("no active Intel(R) RAID "
-                               "controller found under %s\n",controller_path);
-
        return result;
 }
 
 static int export_detail_platform_imsm(int verbose, char *controller_path)
 {
-       const struct imsm_orom *orom;
        struct sys_dev *list, *hba;
        int result=1;
 
@@ -1954,17 +2003,18 @@ static int export_detail_platform_imsm(int verbose, char *controller_path)
        for (hba = list; hba; hba = hba->next) {
                if (controller_path && (compare_paths(hba->path,controller_path) != 0))
                        continue;
-               orom = find_imsm_capability(hba->type);
-               if (!orom) {
-                       if (verbose > 0)
-                               pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path);
-               }
-               else {
-                       print_imsm_capability_export(orom);
+               if (!find_imsm_capability(hba) && verbose > 0)
+                       pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path);
+               else
                        result = 0;
-               }
        }
 
+       const struct orom_entry *oroms = get_oroms();
+       int i;
+
+       for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++)
+               print_imsm_capability_export(&oroms[i].orom);
+
        return result;
 }
 
@@ -2142,7 +2192,7 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map)
        case 5:
                return map->num_members - 1;
        default:
-               dprintf("%s: unsupported raid level\n", __func__);
+               dprintf("unsupported raid level\n");
                return 0;
        }
 }
@@ -2399,7 +2449,7 @@ static int imsm_create_metadata_checkpoint_update(
 
        int update_memory_size = 0;
 
-       dprintf("imsm_create_metadata_checkpoint_update(enter)\n");
+       dprintf("(enter)\n");
 
        if (u == NULL)
                return 0;
@@ -2411,14 +2461,12 @@ static int imsm_create_metadata_checkpoint_update(
 
        *u = xcalloc(1, update_memory_size);
        if (*u == NULL) {
-               dprintf("error: cannot get memory for "
-                       "imsm_create_metadata_checkpoint_update update\n");
+               dprintf("error: cannot get memory\n");
                return 0;
        }
        (*u)->type = update_general_migration_checkpoint;
        (*u)->curr_migr_unit = __le32_to_cpu(super->migr_rec->curr_migr_unit);
-       dprintf("imsm_create_metadata_checkpoint_update: prepared for %u\n",
-               (*u)->curr_migr_unit);
+       dprintf("prepared for %u\n", (*u)->curr_migr_unit);
 
        return update_memory_size;
 }
@@ -2553,9 +2601,7 @@ static unsigned long long imsm_component_size_aligment_check(int level,
        */
        component_size_alligment = component_size % (chunk_size/512);
 
-       dprintf("imsm_component_size_aligment_check(Level: %i, "
-               "chunk_size = %i, component_size = %llu), "
-               "component_size_alligment = %u\n",
+       dprintf("(Level: %i, chunk_size = %i, component_size = %llu), component_size_alligment = %u\n",
                level, chunk_size, component_size,
                component_size_alligment);
 
@@ -2563,7 +2609,7 @@ static unsigned long long imsm_component_size_aligment_check(int level,
                dprintf("imsm: reported component size alligned from %llu ",
                        component_size);
                component_size -= component_size_alligment;
-               dprintf("to %llu (%i).\n",
+               dprintf_cont("to %llu (%i).\n",
                        component_size, component_size_alligment);
        }
 
@@ -2883,7 +2929,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
                 */
                max_enough = max(max_enough, enough);
        }
-       dprintf("%s: enough: %d\n", __func__, max_enough);
+       dprintf("enough: %d\n", max_enough);
        info->container_enough = max_enough;
 
        if (super->disks) {
@@ -3087,13 +3133,18 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
         * use the same Intel hba
         * If not on Intel hba at all, allow anything.
         */
-       if (!check_env("IMSM_NO_PLATFORM")) {
-               if (first->hba && sec->hba &&
-                   strcmp(first->hba->path, sec->hba->path) != 0)  {
+       if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) {
+               if (first->hba->type != sec->hba->type) {
                        fprintf(stderr,
-                               "HBAs of devices does not match %s != %s\n",
-                               first->hba ? first->hba->path : NULL,
-                               sec->hba ? sec->hba->path : NULL);
+                               "HBAs of devices do not match %s != %s\n",
+                               get_sys_dev_type(first->hba->type),
+                               get_sys_dev_type(sec->hba->type));
+                       return 3;
+               }
+               if (first->orom != sec->orom) {
+                       fprintf(stderr,
+                               "HBAs of devices do not match %s != %s\n",
+                               first->hba->pci_id, sec->hba->pci_id);
                        return 3;
                }
        }
@@ -3606,7 +3657,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        free(anchor);
 
        if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
-               pr_err("%s could not allocate migr_rec buffer\n", __func__);
+               pr_err("could not allocate migr_rec buffer\n");
                free(super->buf);
                return 2;
        }
@@ -3822,9 +3873,9 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                                "    but the container is assigned to Intel(R) "
                                "%s RAID controller (",
                                devname,
-                               hba_name->path,
+                               get_sys_dev_type(hba_name->type),
                                hba_name->pci_id ? : "Err!",
-                               get_sys_dev_type(hba_name->type));
+                               get_sys_dev_type(super->hba->type));
 
                        while (hba) {
                                fprintf(stderr, "%s", hba->pci_id ? : "Err!");
@@ -3832,16 +3883,16 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                                        fprintf(stderr, ", ");
                                hba = hba->next;
                        }
-
-                       fprintf(stderr, ").\n");
-                       cont_err("Mixing devices attached to multiple controllers "
-                                "is not allowed.\n");
+                       fprintf(stderr, ").\n"
+                               "    Mixing devices attached to different controllers "
+                               "is not allowed.\n");
                }
                return 2;
        }
-       super->orom = find_imsm_capability(hba_name->type);
+       super->orom = find_imsm_capability(hba_name);
        if (!super->orom)
                return 3;
+
        return 0;
 }
 
@@ -3906,8 +3957,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size,
 
                if (tbl_mpb->family_num == mpb->family_num) {
                        if (tbl_mpb->check_sum == mpb->check_sum) {
-                               dprintf("%s: mpb from %d:%d matches %d:%d\n",
-                                       __func__, super->disks->major,
+                               dprintf("mpb from %d:%d matches %d:%d\n",
+                                       super->disks->major,
                                        super->disks->minor,
                                        table[i]->disks->major,
                                        table[i]->disks->minor);
@@ -3924,8 +3975,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size,
                                 */
                                struct intel_disk *idisk;
 
-                               dprintf("%s: mpb from %d:%d replaces %d:%d\n",
-                                       __func__, super->disks->major,
+                               dprintf("mpb from %d:%d replaces %d:%d\n",
+                                       super->disks->major,
                                        super->disks->minor,
                                        table[i]->disks->major,
                                        table[i]->disks->minor);
@@ -3953,8 +4004,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size,
                                                idisk->disk.status |= CONFIGURED_DISK;
                                }
 
-                               dprintf("%s: mpb from %d:%d prefer %d:%d\n",
-                                       __func__, super->disks->major,
+                               dprintf("mpb from %d:%d prefer %d:%d\n",
+                                       super->disks->major,
                                        super->disks->minor,
                                        table[i]->disks->major,
                                        table[i]->disks->minor);
@@ -4013,12 +4064,12 @@ validate_members(struct intel_super *super, struct intel_disk *disk_list,
                            idisk->owner == IMSM_UNKNOWN_OWNER)
                                ok_count++;
                        else
-                               dprintf("%s: '%.16s' owner %d != %d\n",
-                                       __func__, disk->serial, idisk->owner,
+                               dprintf("'%.16s' owner %d != %d\n",
+                                       disk->serial, idisk->owner,
                                        owner);
                } else {
-                       dprintf("%s: unknown disk %x [%d]: %.16s\n",
-                               __func__, __le32_to_cpu(mpb->family_num), i,
+                       dprintf("unknown disk %x [%d]: %.16s\n",
+                               __le32_to_cpu(mpb->family_num), i,
                                disk->serial);
                        break;
                }
@@ -4074,8 +4125,8 @@ imsm_thunderdome(struct intel_super **super_list, int len)
                        s = NULL;
 
                if (!s)
-                       dprintf("%s: marking family: %#x from %d:%d offline\n",
-                               __func__, mpb->family_num,
+                       dprintf("marking family: %#x from %d:%d offline\n",
+                               mpb->family_num,
                                super_table[i]->disks->major,
                                super_table[i]->disks->minor);
                super_table[i] = s;
@@ -4422,8 +4473,9 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
 {
        struct intel_super *super;
        int rv;
+       int retry;
 
-       if (!st->ignore_hw_compat && test_partition(fd))
+       if (test_partition(fd))
                /* IMSM not allowed on partitions */
                return 1;
 
@@ -4444,6 +4496,22 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
        }
        rv = load_and_parse_mpb(fd, super, devname, 0);
 
+       /* retry the load if we might have raced against mdmon */
+       if (rv == 3) {
+               struct mdstat_ent *mdstat = mdstat_by_component(fd2devnm(fd));
+
+               if (mdstat && mdmon_running(mdstat->devnm) && getpid() != mdmon_pid(mdstat->devnm)) {
+                       for (retry = 0; retry < 3; retry++) {
+                               usleep(3000);
+                               rv = load_and_parse_mpb(fd, super, devname, 0);
+                               if (rv != 3)
+                                       break;
+                       }
+               }
+
+               free_mdstat(mdstat);
+       }
+
        if (rv) {
                if (devname)
                        pr_err("Failed to load all information "
@@ -4601,8 +4669,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                }
                if (posix_memalign(&super->migr_rec_buf, 512,
                                   MIGR_REC_BUF_SIZE) != 0) {
-                       pr_err("%s could not allocate migr_rec buffer\n",
-                              __func__);
+                       pr_err("could not allocate migr_rec buffer\n");
                        free(super->buf);
                        free(super);
                        free(mpb_new);
@@ -4760,11 +4827,11 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
                super = NULL;
        }
        if (!super) {
-               pr_err("%s could not allocate superblock\n", __func__);
+               pr_err("could not allocate superblock\n");
                return 0;
        }
        if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) {
-               pr_err("%s could not allocate migr_rec buffer\n", __func__);
+               pr_err("could not allocate migr_rec buffer\n");
                free(super->buf);
                free(super);
                return 0;
@@ -4983,6 +5050,14 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        }
 
        get_dev_size(fd, NULL, &size);
+       /* clear migr_rec when adding disk to container */
+       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
+       if (lseek64(fd, size - MIGR_REC_POSITION, SEEK_SET) >= 0) {
+               if (write(fd, super->migr_rec_buf,
+                       MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
+                       perror("Write migr_rec failed");
+       }
+
        size /= 512;
        serialcpy(dd->disk.serial, dd->serial);
        set_total_blocks(&dd->disk, size);
@@ -5018,8 +5093,7 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
         * is prepared.
         */
        if (!st->update_tail) {
-               pr_err("%s shall be used in mdmon context only"
-                      "(line %d).\n", __func__, __LINE__);
+               pr_err("shall be used in mdmon context only\n");
                return 1;
        }
        dd = xcalloc(1, sizeof(*dd));
@@ -5078,8 +5152,8 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
                spare->check_sum = __cpu_to_le32(sum);
 
                if (store_imsm_mpb(d->fd, spare)) {
-                       pr_err("%s: failed for device %d:%d %s\n",
-                               __func__, d->major, d->minor, strerror(errno));
+                       pr_err("failed for device %d:%d %s\n",
+                               d->major, d->minor, strerror(errno));
                        return 1;
                }
                if (doclose) {
@@ -5172,8 +5246,8 @@ static int write_super_imsm(struct supertype *st, int doclose)
 
                if (store_imsm_mpb(d->fd, mpb))
                        fprintf(stderr,
-                               "%s: failed for device %d:%d (fd: %d)%s\n",
-                               __func__, d->major, d->minor,
+                               "failed for device %d:%d (fd: %d)%s\n",
+                               d->major, d->minor,
                                d->fd, strerror(errno));
 
                if (doclose) {
@@ -5210,6 +5284,8 @@ static int create_array(struct supertype *st, int dev_idx)
                int idx = get_imsm_disk_idx(dev, i, MAP_X);
 
                disk = get_imsm_disk(super, idx);
+               if (!disk)
+                       disk = get_imsm_missing(super, idx);
                serialcpy(inf[i].serial, disk->serial);
        }
        append_metadata_update(st, u, len);
@@ -5326,7 +5402,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
 #if DEBUG
                char str[256];
                fd2devname(fd, str);
-               dprintf("validate_geometry_imsm_container: fd: %d %s orom: %p rv: %d raiddisk: %d\n",
+               dprintf("fd: %d %s orom: %p rv: %d raiddisk: %d\n",
                        fd, str, super->orom, rv, raiddisks);
 #endif
                /* no orom/efi or non-intel hba of the disk */
@@ -5660,27 +5736,27 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                tmpdev->container = 0;
                dfd = dev_open(devname, O_RDONLY|O_EXCL);
                if (dfd < 0) {
-                       dprintf("cannot open device %s: %s\n",
+                       dprintf("cannot open device %s: %s\n",
                                devname, strerror(errno));
                        tmpdev->used = 2;
                } else if (fstat(dfd, &stb)< 0) {
                        /* Impossible! */
-                       dprintf("fstat failed for %s: %s\n",
+                       dprintf("fstat failed for %s: %s\n",
                                devname, strerror(errno));
                        tmpdev->used = 2;
                } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
-                       dprintf("%s is not a block device.\n",
+                       dprintf("%s is not a block device.\n",
                                devname);
                        tmpdev->used = 2;
                } else if (must_be_container(dfd)) {
                        struct supertype *cst;
                        cst = super_by_fd(dfd, NULL);
                        if (cst == NULL) {
-                               dprintf("cannot recognize container type %s\n",
+                               dprintf("cannot recognize container type %s\n",
                                        devname);
                                tmpdev->used = 2;
                        } else if (tst->ss != st->ss) {
-                               dprintf("non-imsm container - ignore it: %s\n",
+                               dprintf("non-imsm container - ignore it: %s\n",
                                        devname);
                                tmpdev->used = 2;
                        } else if (!tst->ss->load_container ||
@@ -5694,11 +5770,11 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                } else {
                        tmpdev->st_rdev = stb.st_rdev;
                        if (tst->ss->load_super(tst,dfd, NULL)) {
-                               dprintf("no RAID superblock on %s\n",
+                               dprintf("no RAID superblock on %s\n",
                                        devname);
                                tmpdev->used = 2;
                        } else if (tst->ss->compare_super == NULL) {
-                               dprintf("Cannot assemble %s metadata on %s\n",
+                               dprintf("Cannot assemble %s metadata on %s\n",
                                        tst->ss->name, devname);
                                tmpdev->used = 2;
                        }
@@ -5735,7 +5811,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                                 * Or, if we are auto assembling, we just ignore the second
                                 * for now.
                                 */
-                               dprintf("superblock on %s doesn't match others - assembly aborted\n",
+                               dprintf("superblock on %s doesn't match others - assembly aborted\n",
                                        devname);
                                goto loop;
                        }
@@ -5757,7 +5833,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                                if (iter->array.state & (1<<MD_SB_BLOCK_VOLUME)) {
                                        /* do not assemble arrays with unsupported
                                           configurations */
-                                       dprintf("Cannot activate member %s.\n",
+                                       dprintf("Cannot activate member %s.\n",
                                                iter->text_version);
                                } else
                                        count++;
@@ -5765,11 +5841,11 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                        sysfs_free(head);
 
                } else {
-                       dprintf(" no valid super block on device list: err: %d %p\n",
+                       dprintf("No valid super block on device list: err: %d %p\n",
                                err, st->sb);
                }
        } else {
-               dprintf(" no more devices to examin\n");
+               dprintf("no more devices to examine\n");
        }
 
        for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
@@ -5803,7 +5879,7 @@ count_volumes(char *hba, int dpa, int verbose)
                return 0;
 
        count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose);
-       dprintf(" path: %s active arrays: %d\n", hba, count);
+       dprintf("path: %s active arrays: %d\n", hba, count);
        if (devlist == NULL)
                return 0;
        do  {
@@ -5854,10 +5930,10 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
                return 0;
        }
 
-       if (chunk && (*chunk == 0 || *chunk == UnSet))
+       if (*chunk == 0 || *chunk == UnSet)
                *chunk = imsm_default_chunk(super->orom);
 
-       if (super->orom && chunk && !imsm_orom_has_chunk(super->orom, *chunk)) {
+       if (super->orom && !imsm_orom_has_chunk(super->orom, *chunk)) {
                pr_vrb(": platform does not support a chunk size of: "
                       "%d\n", *chunk);
                return 0;
@@ -5874,11 +5950,12 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
                return 0;
        }
 
-       if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 && chunk &&
+       if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 &&
                        (calc_array_size(level, raiddisks, layout, *chunk, size) >> 32) > 0) {
                pr_vrb(": platform does not support a volume size over 2TB\n");
                return 0;
        }
+
        return 1;
 }
 
@@ -6188,7 +6265,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                /* Must be a fresh device to add to a container */
                return validate_geometry_imsm_container(st, level, layout,
                                                        raiddisks,
-                                                       chunk?*chunk:0,
+                                                       *chunk,
                                                        size, data_offset,
                                                        dev, freesize,
                                                        verbose);
@@ -6224,7 +6301,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                        }
                        if (freesize)
                                return reserve_space(st, raiddisks, size,
-                                                    chunk?*chunk:0, freesize);
+                                                    *chunk, freesize);
                }
                return 1;
        }
@@ -6501,7 +6578,7 @@ static void update_recovery_start(struct intel_super *super,
                 * IMSM_ORD_REBUILD, so assume they are missing and the
                 * disk_ord_tbl was not correctly updated
                 */
-               dprintf("%s: failed to locate out-of-sync disk\n", __func__);
+               dprintf("failed to locate out-of-sync disk\n");
                return;
        }
 
@@ -6822,8 +6899,7 @@ static int imsm_open_new(struct supertype *c, struct active_array *a,
        struct imsm_super *mpb = super->anchor;
 
        if (atoi(inst) >= mpb->num_raid_devs) {
-               pr_err("%s: subarry index %d, out of range\n",
-                       __func__, atoi(inst));
+               pr_err("subarry index %d, out of range\n", atoi(inst));
                return -ENODEV;
        }
 
@@ -7236,7 +7312,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
        case IMSM_T_STATE_NORMAL: /* transition to normal state */
                dprintf("normal: ");
                if (is_rebuilding(dev)) {
-                       dprintf("while rebuilding");
+                       dprintf_cont("while rebuilding");
                        /* check if recovery is really finished */
                        for (mdi = a->info.devs; mdi ; mdi = mdi->next)
                                if (mdi->recovery_start != MaxSector) {
@@ -7244,8 +7320,8 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                                        break;
                                }
                        if (recovery_not_finished) {
-                               dprintf("\nimsm: Rebuild has not finished yet, "
-                                               "state not changed");
+                               dprintf_cont("\n");
+                               dprintf("Rebuild has not finished yet, state not changed");
                                if (a->last_checkpoint < mdi->recovery_start) {
                                        a->last_checkpoint = mdi->recovery_start;
                                        super->updates_pending++;
@@ -7260,7 +7336,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                        break;
                }
                if (is_gen_migration(dev)) {
-                       dprintf("while general migration");
+                       dprintf_cont("while general migration");
                        if (a->last_checkpoint >= a->info.component_size)
                                end_migration(dev, super, map_state);
                        else
@@ -7272,26 +7348,26 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                }
        break;
        case IMSM_T_STATE_DEGRADED: /* transition to degraded state */
-               dprintf("degraded: ");
+               dprintf_cont("degraded: ");
                if ((map->map_state != map_state) &&
                    !dev->vol.migr_state) {
-                       dprintf("mark degraded");
+                       dprintf_cont("mark degraded");
                        map->map_state = map_state;
                        super->updates_pending++;
                        a->last_checkpoint = 0;
                        break;
                }
                if (is_rebuilding(dev)) {
-                       dprintf("while rebuilding.");
+                       dprintf_cont("while rebuilding.");
                        if (map->map_state != map_state)  {
-                               dprintf(" Map state change");
+                               dprintf_cont(" Map state change");
                                end_migration(dev, super, map_state);
                                super->updates_pending++;
                        }
                        break;
                }
                if (is_gen_migration(dev)) {
-                       dprintf("while general migration");
+                       dprintf_cont("while general migration");
                        if (a->last_checkpoint >= a->info.component_size)
                                end_migration(dev, super, map_state);
                        else {
@@ -7302,22 +7378,22 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                        break;
                }
                if (is_initializing(dev)) {
-                       dprintf("while initialization.");
+                       dprintf_cont("while initialization.");
                        map->map_state = map_state;
                        super->updates_pending++;
                        break;
                }
        break;
        case IMSM_T_STATE_FAILED: /* transition to failed state */
-               dprintf("failed: ");
+               dprintf_cont("failed: ");
                if (is_gen_migration(dev)) {
-                       dprintf("while general migration");
+                       dprintf_cont("while general migration");
                        map->map_state = map_state;
                        super->updates_pending++;
                        break;
                }
                if (map->map_state != map_state) {
-                       dprintf("mark failed");
+                       dprintf_cont("mark failed");
                        end_migration(dev, super, map_state);
                        super->updates_pending++;
                        a->last_checkpoint = 0;
@@ -7325,10 +7401,9 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
                }
        break;
        default:
-               dprintf("state %i\n", map_state);
+               dprintf_cont("state %i\n", map_state);
        }
-       dprintf("\n");
-
+       dprintf_cont("\n");
 }
 
 static int store_imsm_mpb(int fd, struct imsm_super *mpb)
@@ -7390,7 +7465,7 @@ static struct dl *imsm_readd(struct intel_super *super, int idx, struct active_a
                dl = NULL;
 
        if (dl)
-               dprintf("%s: found %x:%x\n", __func__, dl->major, dl->minor);
+               dprintf("found %x:%x\n", dl->major, dl->minor);
 
        return dl;
 }
@@ -7757,8 +7832,7 @@ static int remove_disk_super(struct intel_super *super, int major, int minor)
                                super->disks = dl->next;
                        dl->next = NULL;
                        __free_imsm_disk(dl);
-                       dprintf("%s: removed %x:%x\n",
-                               __func__, major, minor);
+                       dprintf("removed %x:%x\n", major, minor);
                        break;
                }
                prev = dl;
@@ -7784,9 +7858,8 @@ static int add_remove_disk_update(struct intel_super *super)
                        disk_cfg->next = super->disks;
                        super->disks = disk_cfg;
                        check_degraded = 1;
-                       dprintf("%s: added %x:%x\n",
-                               __func__, disk_cfg->major,
-                               disk_cfg->minor);
+                       dprintf("added %x:%x\n",
+                               disk_cfg->major, disk_cfg->minor);
                } else if (disk_cfg->action == DISK_REMOVE) {
                        dprintf("Disk remove action processed: %x.%x\n",
                                disk_cfg->major, disk_cfg->minor);
@@ -7818,7 +7891,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
        void **tofree = NULL;
        int ret_val = 0;
 
-       dprintf("apply_reshape_migration_update()\n");
+       dprintf("(enter)\n");
        if ((u->subdev < 0) ||
            (u->subdev > 1)) {
                dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
@@ -7938,7 +8011,7 @@ static int apply_size_change_update(struct imsm_update_size_change *u,
        struct intel_dev *id;
        int ret_val = 0;
 
-       dprintf("apply_size_change_update()\n");
+       dprintf("(enter)\n");
        if ((u->subdev < 0) ||
            (u->subdev > 1)) {
                dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
@@ -7955,8 +8028,7 @@ static int apply_size_change_update(struct imsm_update_size_change *u,
                        /* calculate new size
                         */
                        blocks_per_member = u->new_size / used_disks;
-                       dprintf("imsm: apply_size_change_update(size: %llu, "
-                               "blocks per member: %llu)\n",
+                       dprintf("(size: %llu, blocks per member: %llu)\n",
                                u->new_size, blocks_per_member);
                        set_blocks_per_member(map, blocks_per_member);
                        imsm_set_array_size(dev, u->new_size);
@@ -8099,7 +8171,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
        int ret_val = 0;
        unsigned int dev_id;
 
-       dprintf("imsm: apply_reshape_container_disks_update()\n");
+       dprintf("(enter)\n");
 
        /* enable spares to use in array */
        for (i = 0; i < delta_disks; i++) {
@@ -8340,8 +8412,7 @@ static void imsm_process_update(struct supertype *st,
                struct imsm_update_general_migration_checkpoint *u =
                                                        (void *)update->buf;
 
-               dprintf("imsm: process_update() "
-                       "for update_general_migration_checkpoint called\n");
+               dprintf("called for update_general_migration_checkpoint\n");
 
                /* find device under general migration */
                for (id = super->devlist ; id; id = id->next) {
@@ -8410,15 +8481,14 @@ static void imsm_process_update(struct supertype *st,
 
                /* handle racing creates: first come first serve */
                if (u->dev_idx < mpb->num_raid_devs) {
-                       dprintf("%s: subarray %d already defined\n",
-                               __func__, u->dev_idx);
+                       dprintf("subarray %d already defined\n", u->dev_idx);
                        goto create_error;
                }
 
                /* check update is next in sequence */
                if (u->dev_idx != mpb->num_raid_devs) {
-                       dprintf("%s: can not create array %d expected index %d\n",
-                               __func__, u->dev_idx, mpb->num_raid_devs);
+                       dprintf("can not create array %d expected index %d\n",
+                               u->dev_idx, mpb->num_raid_devs);
                        goto create_error;
                }
 
@@ -8443,14 +8513,14 @@ static void imsm_process_update(struct supertype *st,
                                continue;
 
                        if (disks_overlap(super, i, u)) {
-                               dprintf("%s: arrays overlap\n", __func__);
+                               dprintf("arrays overlap\n");
                                goto create_error;
                        }
                }
 
                /* check that prepare update was successful */
                if (!update->space) {
-                       dprintf("%s: prepare update failed\n", __func__);
+                       dprintf("prepare update failed\n");
                        goto create_error;
                }
 
@@ -8462,7 +8532,7 @@ static void imsm_process_update(struct supertype *st,
                for (i = 0; i < new_map->num_members; i++) {
                        dl = serial_to_dl(inf[i].serial, super);
                        if (!dl) {
-                               dprintf("%s: disk disappeared\n", __func__);
+                               dprintf("disk disappeared\n");
                                goto create_error;
                        }
                }
@@ -8568,7 +8638,7 @@ static void imsm_process_update(struct supertype *st,
        }
        case update_add_remove_disk: {
                /* we may be able to repair some arrays if disks are
-                * being added, check teh status of add_remove_disk
+                * being added, check the status of add_remove_disk
                 * if discs has been added.
                 */
                if (add_remove_disk_update(super)) {
@@ -8588,8 +8658,8 @@ static void imsm_process_update(struct supertype *st,
 
 static struct mdinfo *get_spares_for_grow(struct supertype *st);
 
-static void imsm_prepare_update(struct supertype *st,
-                               struct metadata_update *update)
+static int imsm_prepare_update(struct supertype *st,
+                              struct metadata_update *update)
 {
        /**
         * Allocate space to hold new disk entries, raid-device entries or a new
@@ -8598,19 +8668,27 @@ static void imsm_prepare_update(struct supertype *st,
         * integrated by the monitor thread without worrying about live pointers
         * in the manager thread.
         */
-       enum imsm_update_type type = *(enum imsm_update_type *) update->buf;
+       enum imsm_update_type type;
        struct intel_super *super = st->sb;
        struct imsm_super *mpb = super->anchor;
        size_t buf_len;
        size_t len = 0;
 
+       if (update->len < (int)sizeof(type))
+               return 0;
+
+       type = *(enum imsm_update_type *) update->buf;
+
        switch (type) {
        case update_general_migration_checkpoint:
-               dprintf("imsm: prepare_update() "
-                       "for update_general_migration_checkpoint called\n");
+               if (update->len < (int)sizeof(struct imsm_update_general_migration_checkpoint))
+                       return 0;
+               dprintf("called for update_general_migration_checkpoint\n");
                break;
        case update_takeover: {
                struct imsm_update_takeover *u = (void *)update->buf;
+               if (update->len < (int)sizeof(*u))
+                       return 0;
                if (u->direction == R0_TO_R10) {
                        void **tail = (void **)&update->space_list;
                        struct imsm_dev *dev = get_imsm_dev(super, u->subarray);
@@ -8651,7 +8729,10 @@ static void imsm_prepare_update(struct supertype *st,
                struct intel_dev *dl;
                void **space_tail = (void**)&update->space_list;
 
-               dprintf("imsm: imsm_prepare_update() for update_reshape\n");
+               if (update->len < (int)sizeof(*u))
+                       return 0;
+
+               dprintf("for update_reshape\n");
 
                for (dl = super->devlist; dl; dl = dl->next) {
                        int size = sizeof_imsm_dev(dl->dev, 1);
@@ -8683,7 +8764,10 @@ static void imsm_prepare_update(struct supertype *st,
                void *s;
                int current_level = -1;
 
-               dprintf("imsm: imsm_prepare_update() for update_reshape\n");
+               if (update->len < (int)sizeof(*u))
+                       return 0;
+
+               dprintf("for update_reshape\n");
 
                /* add space for bigger array in update
                 */
@@ -8750,6 +8834,13 @@ static void imsm_prepare_update(struct supertype *st,
                break;
        }
        case update_size_change: {
+               if (update->len < (int)sizeof(struct imsm_update_size_change))
+                       return 0;
+               break;
+       }
+       case update_activate_spare: {
+               if (update->len < (int)sizeof(struct imsm_update_activate_spare))
+                       return 0;
                break;
        }
        case update_create_array: {
@@ -8762,6 +8853,9 @@ static void imsm_prepare_update(struct supertype *st,
                int i;
                int activate = 0;
 
+               if (update->len < (int)sizeof(*u))
+                       return 0;
+
                inf = get_disk_info(u);
                len = sizeof_imsm_dev(dev, 1);
                /* allocate a new super->devlist entry */
@@ -8783,9 +8877,22 @@ static void imsm_prepare_update(struct supertype *st,
                }
                len += activate * sizeof(struct imsm_disk);
                break;
-       default:
+       }
+       case update_kill_array: {
+               if (update->len < (int)sizeof(struct imsm_update_kill_array))
+                       return 0;
+               break;
+       }
+       case update_rename_array: {
+               if (update->len < (int)sizeof(struct imsm_update_rename_array))
+                       return 0;
                break;
        }
+       case update_add_remove_disk:
+               /* no update->len needed */
+               break;
+       default:
+               return 0;
        }
 
        /* check if we need a larger metadata buffer */
@@ -8809,6 +8916,7 @@ static void imsm_prepare_update(struct supertype *st,
                else
                        super->next_buf = NULL;
        }
+       return 1;
 }
 
 /* must be called while manager is quiesced */
@@ -8821,8 +8929,7 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
        int i, j, num_members;
        __u32 ord;
 
-       dprintf("%s: deleting device[%d] from imsm_super\n",
-               __func__, index);
+       dprintf("deleting device[%d] from imsm_super\n", index);
 
        /* shift all indexes down one */
        for (iter = super->disks; iter; iter = iter->next)
@@ -8990,6 +9097,83 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
        return 0;
 }
 
+/*******************************************************************************
+ * Function:   validate_container_imsm
+ * Description: This routine validates container after assemble,
+ *             eg. if devices in container are under the same controller.
+ *
+ * Parameters:
+ *     info    : linked list with info about devices used in array
+ * Returns:
+ *     1 : HBA mismatch
+ *     0 : Success
+ ******************************************************************************/
+int validate_container_imsm(struct mdinfo *info)
+{
+       if (check_env("IMSM_NO_PLATFORM"))
+               return 0;
+
+       struct sys_dev *idev;
+       struct sys_dev *hba = NULL;
+       struct sys_dev *intel_devices = find_intel_devices();
+       char *dev_path = devt_to_devpath(makedev(info->disk.major,
+                                                                       info->disk.minor));
+
+       for (idev = intel_devices; idev; idev = idev->next) {
+               if (dev_path && strstr(dev_path, idev->path)) {
+                       hba = idev;
+                       break;
+               }
+       }
+       if (dev_path)
+               free(dev_path);
+
+       if (!hba) {
+               pr_err("WARNING - Cannot detect HBA for device %s!\n",
+                               devid2kname(makedev(info->disk.major, info->disk.minor)));
+               return 1;
+       }
+
+       const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id);
+       struct mdinfo *dev;
+
+       for (dev = info->next; dev; dev = dev->next) {
+               dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor));
+
+               struct sys_dev *hba2 = NULL;
+               for (idev = intel_devices; idev; idev = idev->next) {
+                       if (dev_path && strstr(dev_path, idev->path)) {
+                               hba2 = idev;
+                               break;
+                       }
+               }
+               if (dev_path)
+                       free(dev_path);
+
+               const struct imsm_orom *orom2 = hba2 == NULL ? NULL :
+                               get_orom_by_device_id(hba2->dev_id);
+
+               if (hba2 && hba->type != hba2->type) {
+                       pr_err("WARNING - HBAs of devices do not match %s != %s\n",
+                               get_sys_dev_type(hba->type), get_sys_dev_type(hba2->type));
+                       return 1;
+               }
+
+               if (orom != orom2) {
+                       pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n"
+                               "       This operation is not supported and can lead to data loss.\n");
+                       return 1;
+               }
+
+               if (!orom) {
+                       pr_err("WARNING - IMSM container assembled with disks under HBAs without IMSM platform support!\n"
+                               "       This operation is not supported and can lead to data loss.\n");
+                       return 1;
+               }
+       }
+
+       return 0;
+}
 #ifndef MDASSEMBLE
 /*******************************************************************************
  * Function:   init_migr_record_imsm
@@ -9338,7 +9522,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
        char *drv=NULL;
        struct stat st;
 
-       strncpy(disk_path, disk_by_path, PATH_MAX - 1);
+       strcpy(disk_path, disk_by_path);
        strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
        if (stat(disk_path, &st) == 0) {
                struct sys_dev* hba;
@@ -9481,9 +9665,9 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                ret_val = 1;
 
        if (ret_val)
-               dprintf("\tContainer operation allowed\n");
+               dprintf("Container operation allowed\n");
        else
-               dprintf("\tError: %i\n", ret_val);
+               dprintf("Error: %i\n", ret_val);
 
        return ret_val;
 }
@@ -9521,8 +9705,7 @@ static int imsm_create_metadata_update_for_reshape(
        int delta_disks = 0;
        struct mdinfo *dev;
 
-       dprintf("imsm_update_metadata_for_reshape(enter) raid_disks = %i\n",
-               geo->raid_disks);
+       dprintf("(enter) raid_disks = %i\n", geo->raid_disks);
 
        delta_disks = geo->raid_disks - old_raid_disks;
 
@@ -9576,12 +9759,12 @@ abort:
 
        dprintf("imsm: reshape update preparation :");
        if (i == delta_disks) {
-               dprintf(" OK\n");
+               dprintf_cont(" OK\n");
                *updatep = u;
                return update_memory_size;
        }
        free(u);
-       dprintf(" Error\n");
+       dprintf_cont(" Error\n");
 
        return 0;
 }
@@ -9600,8 +9783,7 @@ static int imsm_create_metadata_update_for_size_change(
        int update_memory_size = 0;
        struct imsm_update_size_change *u = NULL;
 
-       dprintf("imsm_create_metadata_update_for_size_change(enter)"
-               " New size = %llu\n", geo->size);
+       dprintf("(enter) New size = %llu\n", geo->size);
 
        /* size of all update data without anchor */
        update_memory_size = sizeof(struct imsm_update_size_change);
@@ -9633,8 +9815,7 @@ static int imsm_create_metadata_update_for_migration(
        struct imsm_dev *dev;
        int previous_level = -1;
 
-       dprintf("imsm_create_metadata_update_for_migration(enter)"
-               " New Level = %i\n", geo->level);
+       dprintf("(enter) New Level = %i\n", geo->level);
 
        /* size of all update data without anchor */
        update_memory_size = sizeof(struct imsm_update_reshape_migration);
@@ -9697,8 +9878,8 @@ static void imsm_update_metadata_locally(struct supertype *st,
        mu.space = NULL;
        mu.space_list = NULL;
        mu.next = NULL;
-       imsm_prepare_update(st, &mu);
-       imsm_process_update(st, &mu);
+       if (imsm_prepare_update(st, &mu))
+               imsm_process_update(st, &mu);
 
        while (mu.space_list) {
                void **space = mu.space_list;
@@ -9980,7 +10161,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
        int ret_val = 1;
        struct geo_params geo;
 
-       dprintf("imsm: reshape_super called.\n");
+       dprintf("(enter)\n");
 
        memset(&geo, 0, sizeof(struct geo_params));
 
@@ -9994,8 +10175,8 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
        if (delta_disks != UnSet)
                geo.raid_disks += delta_disks;
 
-       dprintf("\tfor level      : %i\n", geo.level);
-       dprintf("\tfor raid_disks : %i\n", geo.raid_disks);
+       dprintf("for level      : %i\n", geo.level);
+       dprintf("for raid_disks : %i\n", geo.raid_disks);
 
        if (experimental() == 0)
                return ret_val;
@@ -10132,21 +10313,18 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
        unsigned long long position_to_set = to_complete / ndata;
 
        if (fd < 0) {
-               dprintf("imsm: wait_for_reshape_imsm() "
-                       "cannot open reshape_position\n");
+               dprintf("cannot open reshape_position\n");
                return 1;
        }
 
        if (sysfs_fd_get_ll(fd, &completed) < 0) {
-               dprintf("imsm: wait_for_reshape_imsm() "
-                       "cannot read reshape_position (no reshape in progres)\n");
+               dprintf("cannot read reshape_position (no reshape in progres)\n");
                close(fd);
                return 0;
        }
 
        if (completed > position_to_set) {
-               dprintf("imsm: wait_for_reshape_imsm() "
-                       "wrong next position to set %llu (%llu)\n",
+               dprintf("wrong next position to set %llu (%llu)\n",
                        to_complete, position_to_set);
                close(fd);
                return -1;
@@ -10154,8 +10332,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
        dprintf("Position set: %llu\n", position_to_set);
        if (sysfs_set_num(sra, NULL, "sync_max",
                          position_to_set) != 0) {
-               dprintf("imsm: wait_for_reshape_imsm() "
-                       "cannot set reshape position to %llu\n",
+               dprintf("cannot set reshape position to %llu\n",
                        position_to_set);
                close(fd);
                return -1;
@@ -10169,8 +10346,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
                                strncmp(action, "reshape", 7) != 0)
                        break;
                if (sysfs_fd_get_ll(fd, &completed) < 0) {
-                       dprintf("imsm: wait_for_reshape_imsm() "
-                               "cannot read reshape_position (in loop)\n");
+                       dprintf("cannot read reshape_position (in loop)\n");
                        close(fd);
                        return 1;
                }
@@ -10444,6 +10620,8 @@ static int imsm_manage_reshape(
                        dprintf("wait_for_reshape_imsm returned error!\n");
                        goto abort;
                }
+               if (sigterm)
+                       goto abort;
 
                if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) {
                        /* ignore error == 2, this can mean end of reshape here
@@ -10455,6 +10633,24 @@ static int imsm_manage_reshape(
 
        }
 
+       /* clear migr_rec on disks after successful migration */
+       struct dl *d;
+
+       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
+       for (d = super->disks; d; d = d->next) {
+               if (d->index < 0 || is_failed(&d->disk))
+                       continue;
+               unsigned long long dsize;
+
+               get_dev_size(d->fd, NULL, &dsize);
+               if (lseek64(d->fd, dsize - MIGR_REC_POSITION,
+                           SEEK_SET) >= 0) {
+                       if (write(d->fd, super->migr_rec_buf,
+                               MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE)
+                               perror("Write migr_rec failed");
+               }
+       }
+
        /* return '1' if done */
        ret_val = 1;
 abort:
@@ -10463,6 +10659,7 @@ abort:
 
        return ret_val;
 }
+
 #endif /* MDASSEMBLE */
 
 struct superswitch super_imsm = {
@@ -10506,6 +10703,7 @@ struct superswitch super_imsm = {
        .free_super     = free_super_imsm,
        .match_metadata_desc = match_metadata_desc_imsm,
        .container_content = container_content_imsm,
+       .validate_container = validate_container_imsm,
 
        .external       = 1,
        .name = "imsm",