]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: remove redundant characters from some error messages
[thirdparty/mdadm.git] / super-intel.c
index 1ad5e47de91ee344caa13211f20f370658ea0176..cfc8904e2d2cca5df92a54933a3d50ca6ccc5dff 100644 (file)
@@ -101,7 +101,7 @@ struct imsm_disk {
 #define CONFIGURED_DISK __cpu_to_le32(0x02)  /* Member of some RaidDev */
 #define FAILED_DISK     __cpu_to_le32(0x04)  /* Permanent failure */
        __u32 status;                    /* 0xF0 - 0xF3 */
-       __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ 
+       __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */
        __u32 total_blocks_hi;           /* 0xF4 - 0xF5 total blocks hi */
 #define        IMSM_DISK_FILLERS       3
        __u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */
@@ -235,7 +235,6 @@ struct bbm_log {
        struct bbm_log_entry mapped_block_entries[BBM_LOG_MAX_ENTRIES];
 } __attribute__ ((__packed__));
 
-
 #ifndef MDASSEMBLE
 static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
 #endif
@@ -249,7 +248,6 @@ static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed"
                               * 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
@@ -295,7 +293,7 @@ struct md_list {
        struct md_list *next;
 };
 
-#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
+#define pr_vrb(fmt, arg...) (void) (verbose && pr_err(fmt, ##arg))
 
 static __u8 migr_type(struct imsm_dev *dev)
 {
@@ -431,9 +429,9 @@ struct imsm_update_activate_spare {
 };
 
 struct geo_params {
-       int dev_id;
+       char devnm[32];
        char *dev_name;
-       long long size;
+       unsigned long long size;
        int level;
        int layout;
        int chunksize;
@@ -508,11 +506,12 @@ struct imsm_update_add_remove_disk {
        enum imsm_update_type type;
 };
 
-
 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",
+       [SYS_DEV_VMD] = "VMD"
 };
 
 const char *get_sys_dev_type(enum sys_dev_type type)
@@ -525,20 +524,21 @@ const char *get_sys_dev_type(enum sys_dev_type type)
 
 static struct intel_hba * alloc_intel_hba(struct sys_dev *device)
 {
-       struct intel_hba *result = malloc(sizeof(*result));
-       if (result) {
-               result->type = device->type;
-               result->path = strdup(device->path);
-               result->next = NULL;
-               if (result->path && (result->pci_id = strrchr(result->path, '/')) != NULL)
-                       result->pci_id++;
-       }
+       struct intel_hba *result = xmalloc(sizeof(*result));
+
+       result->type = device->type;
+       result->path = xstrdup(device->path);
+       result->next = NULL;
+       if (result->path && (result->pci_id = strrchr(result->path, '/')) != NULL)
+               result->pci_id++;
+
        return result;
 }
 
 static struct intel_hba * find_intel_hba(struct intel_hba *hba, struct sys_dev *device)
 {
-       struct intel_hba *result=NULL;
+       struct intel_hba *result;
+
        for (result = hba; result; result = result->next) {
                if (result->type == device->type && strcmp(result->path, device->path) == 0)
                        break;
@@ -562,11 +562,21 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device
 
        hba = super->hba;
        /* Intel metadata allows for all disks attached to the same type HBA.
-        * Do not sypport odf HBA types mixing
+        * Do not support HBA types mixing
         */
        if (device->type != hba->type)
                return 2;
 
+       /* Always forbid spanning between VMD domains (seen as different controllers by mdadm) */
+       if (device->type == SYS_DEV_VMD && !path_attached_to_hba(device->path, hba->path))
+               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;
 
@@ -576,7 +586,7 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device
 
 static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
 {
-       struct sys_dev *list, *elem, *prev;
+       struct sys_dev *list, *elem;
        char *disk_path;
 
        if ((list = find_intel_devices()) == NULL)
@@ -587,32 +597,19 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
        else
                disk_path = diskfd_to_devpath(fd);
 
-       if (!disk_path) {
-               free_sys_dev(&list);
+       if (!disk_path)
                return 0;
-       }
 
-       for (prev = NULL, elem = list; elem; prev = elem, elem = elem->next) {
-               if (path_attached_to_hba(disk_path, elem->path)) {
-                       if (prev == NULL)
-                               list = list->next;
-                       else
-                               prev->next = elem->next;
-                       elem->next = NULL;
-                       if (disk_path != devname)
-                               free(disk_path);
-                       free_sys_dev(&list);
+       for (elem = list; elem; elem = elem->next)
+               if (path_attached_to_hba(disk_path, elem->path))
                        return elem;
-               }
-       }
+
        if (disk_path != devname)
                free(disk_path);
-       free_sys_dev(&list);
 
        return NULL;
 }
 
-
 static int find_intel_hba_capability(int fd, struct intel_super *super,
                                     char *devname);
 
@@ -625,11 +622,7 @@ static struct supertype *match_metadata_desc_imsm(char *arg)
                )
                return NULL;
 
-       st = malloc(sizeof(*st));
-       if (!st)
-               return NULL;
-       memset(st, 0, sizeof(*st));
-       st->container_dev = NoMdDev;
+       st = xcalloc(1, sizeof(*st));
        st->ss = &super_imsm;
        st->max_devs = IMSM_MAX_DEVICES;
        st->minor_version = 0;
@@ -688,12 +681,12 @@ static __u32 __gen_imsm_checksum(struct imsm_super *mpb)
        __u32 *p = (__u32 *) mpb;
        __u32 sum = 0;
 
-        while (end--) {
-                sum += __le32_to_cpu(*p);
+       while (end--) {
+               sum += __le32_to_cpu(*p);
                p++;
        }
 
-        return sum - __le32_to_cpu(mpb->check_sum);
+       return sum - __le32_to_cpu(mpb->check_sum);
 }
 
 static size_t sizeof_imsm_map(struct imsm_map *map)
@@ -964,9 +957,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
        else
                reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
 
-       rv = malloc(sizeof(struct extent) * (memberships + 1));
-       if (!rv)
-               return NULL;
+       rv = xcalloc(sizeof(struct extent), (memberships + 1));
        e = rv;
 
        for (i = 0; i < super->anchor->num_raid_devs; i++) {
@@ -981,7 +972,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
        }
        qsort(rv, memberships, sizeof(*rv), cmp_extent);
 
-       /* determine the start of the metadata 
+       /* determine the start of the metadata
         * when no raid devices are defined use the default
         * ...otherwise allow the metadata to truncate the value
         * as is the case with older versions of imsm
@@ -1325,12 +1316,12 @@ void examine_migr_rec_imsm(struct intel_super *super)
 /*******************************************************************************
  * function: imsm_check_attributes
  * Description: Function checks if features represented by attributes flags
- *             are supported by mdadm.
+ *             are supported by mdadm.
  * Parameters:
  *             attributes - Attributes read from metadata
  * Returns:
- *             0 - passed attributes contains unsupported features flags
- *             1 - all features are supported
+ *             0 - passed attributes contains unsupported features flags
+ *             1 - all features are supported
  ******************************************************************************/
 static int imsm_check_attributes(__u32 attributes)
 {
@@ -1341,7 +1332,7 @@ static int imsm_check_attributes(__u32 attributes)
 
        not_supported &= attributes;
        if (not_supported) {
-               fprintf(stderr, Name "(IMSM): Unsupported attributes : %x\n",
+               pr_err("(IMSM): Unsupported attributes : %x\n",
                        (unsigned)__le32_to_cpu(not_supported));
                if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
                        dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n");
@@ -1401,7 +1392,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;
        }
@@ -1537,6 +1528,59 @@ static void export_examine_super_imsm(struct supertype *st)
        printf("MD_DEVICES=%u\n", mpb->num_disks);
 }
 
+static int copy_metadata_imsm(struct supertype *st, int from, int to)
+{
+       /* The second last 512byte sector of the device contains
+        * the "struct imsm_super" metadata.
+        * This contains mpb_size which is the size in bytes of the
+        * extended metadata.  This is located immediately before
+        * the imsm_super.
+        * We want to read all that, plus the last sector which
+        * may contain a migration record, and write it all
+        * to the target.
+        */
+       void *buf;
+       unsigned long long dsize, offset;
+       int sectors;
+       struct imsm_super *sb;
+       int written = 0;
+
+       if (posix_memalign(&buf, 4096, 4096) != 0)
+               return 1;
+
+       if (!get_dev_size(from, NULL, &dsize))
+               goto err;
+
+       if (lseek64(from, dsize-1024, 0) < 0)
+               goto err;
+       if (read(from, buf, 512) != 512)
+               goto err;
+       sb = buf;
+       if (strncmp((char*)sb->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0)
+               goto err;
+
+       sectors = mpb_sectors(sb) + 2;
+       offset = dsize - sectors * 512;
+       if (lseek64(from, offset, 0) < 0 ||
+           lseek64(to, offset, 0) < 0)
+               goto err;
+       while (written < sectors * 512) {
+               int n = sectors*512 - written;
+               if (n > 4096)
+                       n = 4096;
+               if (read(from, buf, n) != n)
+                       goto err;
+               if (write(to, buf, n) != n)
+                       goto err;
+               written += n;
+       }
+       free(buf);
+       return 0;
+err:
+       free(buf);
+       return 1;
+}
+
 static void detail_super_imsm(struct supertype *st, char *homehost)
 {
        struct mdinfo info;
@@ -1572,8 +1616,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
        unsigned long port_mask = (1 << port_count) - 1;
 
        if (port_count > (int)sizeof(port_mask) * 8) {
-               if (verbose)
-                       fprintf(stderr, Name ": port_count %d out of range\n", port_count);
+               if (verbose > 0)
+                       pr_err("port_count %d out of range\n", port_count);
                return 2;
        }
 
@@ -1581,7 +1625,10 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
         * this hba
         */
        dir = opendir("/sys/dev/block");
-       for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) {
+       if (!dir)
+               return 1;
+
+       for (ent = readdir(dir); ent; ent = readdir(dir)) {
                int fd;
                char model[64];
                char vendor[64];
@@ -1605,15 +1652,15 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
 
                /* retrieve the scsi device type */
                if (asprintf(&device, "/sys/dev/block/%d:%d/device/xxxxxxx", major, minor) < 0) {
-                       if (verbose)
-                               fprintf(stderr, Name ": failed to allocate 'device'\n");
+                       if (verbose > 0)
+                               pr_err("failed to allocate 'device'\n");
                        err = 2;
                        break;
                }
                sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor);
-               if (load_sys(device, buf) != 0) {
-                       if (verbose)
-                               fprintf(stderr, Name ": failed to read device type for %s\n",
+               if (load_sys(device, buf, sizeof(buf)) != 0) {
+                       if (verbose > 0)
+                               pr_err("failed to read device type for %s\n",
                                        path);
                        err = 2;
                        free(device);
@@ -1626,7 +1673,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
                        vendor[0] = '\0';
                        model[0] = '\0';
                        sprintf(device, "/sys/dev/block/%d:%d/device/vendor", major, minor);
-                       if (load_sys(device, buf) == 0) {
+                       if (load_sys(device, buf, sizeof(buf)) == 0) {
                                strncpy(vendor, buf, sizeof(vendor));
                                vendor[sizeof(vendor) - 1] = '\0';
                                c = (char *) &vendor[sizeof(vendor) - 1];
@@ -1635,7 +1682,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
 
                        }
                        sprintf(device, "/sys/dev/block/%d:%d/device/model", major, minor);
-                       if (load_sys(device, buf) == 0) {
+                       if (load_sys(device, buf, sizeof(buf)) == 0) {
                                strncpy(model, buf, sizeof(model));
                                model[sizeof(model) - 1] = '\0';
                                c = (char *) &model[sizeof(model) - 1];
@@ -1665,18 +1712,19 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
                /* chop device path to 'host%d' and calculate the port number */
                c = strchr(&path[hba_len], '/');
                if (!c) {
-                       if (verbose)
-                               fprintf(stderr, Name ": %s - invalid path name\n", path + hba_len);
+                       if (verbose > 0)
+                               pr_err("%s - invalid path name\n", path + hba_len);
                        err = 2;
                        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) {
+                       if (verbose > 0) {
                                *c = '/'; /* repair the full string */
-                               fprintf(stderr, Name ": failed to determine port number for %s\n",
+                               pr_err("failed to determine port number for %s\n",
                                        path);
                        }
                        err = 2;
@@ -1722,15 +1770,77 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
        return err;
 }
 
+static int print_vmd_attached_devs(struct sys_dev *hba)
+{
+       struct dirent *ent;
+       DIR *dir;
+       char path[292];
+       char link[256];
+       char *c, *rp;
+
+       if (hba->type != SYS_DEV_VMD)
+               return 1;
+
+       /* scroll through /sys/dev/block looking for devices attached to
+        * this hba
+        */
+       dir = opendir("/sys/bus/pci/drivers/nvme");
+       if (!dir)
+               return 1;
+
+       for (ent = readdir(dir); ent; ent = readdir(dir)) {
+               int n;
+
+               /* is 'ent' a device? check that the 'subsystem' link exists and
+                * that its target matches 'bus'
+                */
+               sprintf(path, "/sys/bus/pci/drivers/nvme/%s/subsystem",
+                       ent->d_name);
+               n = readlink(path, link, sizeof(link));
+               if (n < 0 || n >= (int)sizeof(link))
+                       continue;
+               link[n] = '\0';
+               c = strrchr(link, '/');
+               if (!c)
+                       continue;
+               if (strncmp("pci", c+1, strlen("pci")) != 0)
+                       continue;
+
+               sprintf(path, "/sys/bus/pci/drivers/nvme/%s", ent->d_name);
+               /* if not a intel NVMe - skip it*/
+               if (devpath_to_vendor(path) != 0x8086)
+                       continue;
+
+               rp = realpath(path, NULL);
+               if (!rp)
+                       continue;
+
+               if (path_attached_to_hba(rp, hba->path)) {
+                       printf(" NVMe under VMD : %s\n", rp);
+               }
+               free(rp);
+       }
+
+       closedir(dir);
+       return 0;
+}
+
 static void print_found_intel_controllers(struct sys_dev *elem)
 {
        for (; elem; elem = elem->next) {
-               fprintf(stderr, Name ": found Intel(R) ");
+               pr_err("found Intel(R) ");
                if (elem->type == SYS_DEV_SATA)
                        fprintf(stderr, "SATA ");
                else if (elem->type == SYS_DEV_SAS)
                        fprintf(stderr, "SAS ");
-               fprintf(stderr, "RAID controller");
+               else if (elem->type == SYS_DEV_NVME)
+                       fprintf(stderr, "NVMe ");
+
+               if (elem->type == SYS_DEV_VMD)
+                       fprintf(stderr, "VMD domain");
+               else
+                       fprintf(stderr, "RAID controller");
+
                if (elem->pci_id)
                        fprintf(stderr, " at %s", elem->pci_id);
                fprintf(stderr, ".\n");
@@ -1751,7 +1861,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;
@@ -1767,9 +1878,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" : "",
@@ -1798,12 +1915,49 @@ 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 int detail_platform_imsm(int verbose, int enumerate_only)
+static void print_imsm_capability_export(const struct imsm_orom *orom)
+{
+       printf("MD_FIRMWARE_TYPE=imsm\n");
+       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 " : "",
+                       imsm_orom_has_raid1e(orom) ? "raid1e " : "",
+                       imsm_orom_has_raid5(orom) ? "raid10 " : "",
+                       imsm_orom_has_raid10(orom) ? "raid5 " : "");
+       printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+                       imsm_orom_has_chunk(orom, 2) ? "2k " : "",
+                       imsm_orom_has_chunk(orom, 4) ? "4k " : "",
+                       imsm_orom_has_chunk(orom, 8) ? "8k " : "",
+                       imsm_orom_has_chunk(orom, 16) ? "16k " : "",
+                       imsm_orom_has_chunk(orom, 32) ? "32k " : "",
+                       imsm_orom_has_chunk(orom, 64) ? "64k " : "",
+                       imsm_orom_has_chunk(orom, 128) ? "128k " : "",
+                       imsm_orom_has_chunk(orom, 256) ? "256k " : "",
+                       imsm_orom_has_chunk(orom, 512) ? "512k " : "",
+                       imsm_orom_has_chunk(orom, 1024*1) ? "1M " : "",
+                       imsm_orom_has_chunk(orom, 1024*2) ? "2M " : "",
+                       imsm_orom_has_chunk(orom, 1024*4) ? "4M " : "",
+                       imsm_orom_has_chunk(orom, 1024*8) ? "8M " : "",
+                       imsm_orom_has_chunk(orom, 1024*16) ? "16M " : "",
+                       imsm_orom_has_chunk(orom, 1024*32) ? "32M " : "",
+                       imsm_orom_has_chunk(orom, 1024*64) ? "64M " : "");
+       printf("IMSM_2TB_VOLUMES=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB) ? "yes" : "no");
+       printf("IMSM_2TB_DISKS=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "yes" : "no");
+       printf("IMSM_MAX_DISKS=%d\n",orom->tds);
+       printf("IMSM_MAX_VOLUMES_PER_ARRAY=%d\n",orom->vpa);
+       printf("IMSM_MAX_VOLUMES_PER_CONTROLLER=%d\n",orom->vphba);
+}
+
+static int detail_platform_imsm(int verbose, int enumerate_only, char *controller_path)
 {
        /* There are two components to imsm platform support, the ahci SATA
         * controller and the option-rom.  To find the SATA controller we
@@ -1816,11 +1970,10 @@ static int detail_platform_imsm(int verbose, int enumerate_only)
         * 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;
-       int result=0;
+       int result=1;
 
        if (enumerate_only) {
                if (check_env("IMSM_NO_PLATFORM"))
@@ -1829,53 +1982,136 @@ static int detail_platform_imsm(int verbose, int enumerate_only)
                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 = 2;
                }
-               free_sys_dev(&list);
                return result;
        }
 
        list = find_intel_devices();
        if (!list) {
-               if (verbose)
-                       fprintf(stderr, Name ": no active Intel(R) RAID "
-                               "controller found.\n");
-               free_sys_dev(&list);
+               if (verbose > 0)
+                       pr_err("no active Intel(R) RAID controller found.\n");
                return 2;
-       } else if (verbose)
+       } else if (verbose > 0)
                print_found_intel_controllers(list);
 
        for (hba = list; hba; hba = hba->next) {
-               orom = find_imsm_capability(hba->type);
-               if (!orom)
-                       fprintf(stderr, Name ": imsm capabilities not found for controller: %s (type %s)\n",
+               if (controller_path && (compare_paths(hba->path, controller_path) != 0))
+                       continue;
+               if (!find_imsm_capability(hba)) {
+                       char buf[PATH_MAX];
+                       pr_err("imsm capabilities not found for controller: %s (type %s)\n",
+                                 hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path,
+                                 get_sys_dev_type(hba->type));
+                       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 *entry;
+
+       for (entry = orom_entries; entry; entry = entry->next) {
+               if (entry->type == SYS_DEV_VMD) {
+                       for (hba = list; hba; hba = hba->next) {
+                               if (hba->type == SYS_DEV_VMD) {
+                                       char buf[PATH_MAX];
+                                       print_imsm_capability(&entry->orom);
+                                       printf(" I/O Controller : %s (%s)\n",
+                                               vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type));
+                                       if (print_vmd_attached_devs(hba)) {
+                                               if (verbose > 0)
+                                                       pr_err("failed to get devices attached to VMD domain.\n");
+                                               result |= 2;
+                                       }
+                                       printf("\n");
+                               }
+                       }
+                       continue;
+               }
+
+               print_imsm_capability(&entry->orom);
+               if (entry->type == SYS_DEV_NVME) {
+                       for (hba = list; hba; hba = hba->next) {
+                               if (hba->type == SYS_DEV_NVME)
+                                       printf("    NVMe Device : %s\n", hba->path);
+                       }
+                       printf("\n");
+                       continue;
+               }
+
+               struct devid_list *devid;
+               for (devid = entry->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));
-               else
-                       print_imsm_capability(orom);
+                       if (hba->type == SYS_DEV_SATA) {
+                               host_base = ahci_get_port_count(hba->path, &port_count);
+                               if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) {
+                                       if (verbose > 0)
+                                               pr_err("failed to enumerate ports on SATA controller at %s.\n", hba->pci_id);
+                                       result |= 2;
+                               }
+                       }
+               }
+               printf("\n");
+       }
+
+       return result;
+}
+
+static int export_detail_platform_imsm(int verbose, char *controller_path)
+{
+       struct sys_dev *list, *hba;
+       int result=1;
+
+       list = find_intel_devices();
+       if (!list) {
+               if (verbose > 0)
+                       pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_INTEL_DEVICES\n");
+               result = 2;
+               return result;
        }
 
        for (hba = list; hba; hba = hba->next) {
-               printf(" I/O Controller : %s (%s)\n",
-                       hba->path, get_sys_dev_type(hba->type));
-
-               if (hba->type == SYS_DEV_SATA) {
-                       host_base = ahci_get_port_count(hba->path, &port_count);
-                       if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) {
-                               if (verbose)
-                                       fprintf(stderr, Name ": failed to enumerate "
-                                               "ports on SATA controller at %s.", hba->pci_id);
-                               result |= 2;
-                       }
+               if (controller_path && (compare_paths(hba->path,controller_path) != 0))
+                       continue;
+               if (!find_imsm_capability(hba) && verbose > 0) {
+                       char buf[PATH_MAX];
+                       pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",
+                       hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path);
+               }
+               else
+                       result = 0;
+       }
+
+       const struct orom_entry *entry;
+
+       for (entry = orom_entries; entry; entry = entry->next) {
+               if (entry->type == SYS_DEV_VMD) {
+                       for (hba = list; hba; hba = hba->next)
+                               print_imsm_capability_export(&entry->orom);
+                       continue;
                }
+               print_imsm_capability_export(&entry->orom);
        }
 
-       free_sys_dev(&list);
        return result;
 }
+
 #endif
 
 static int match_home_imsm(struct supertype *st, char *homehost)
@@ -1902,7 +2138,7 @@ static void uuid_from_super_imsm(struct supertype *st, int uuid[4])
         *    not the device-set.
         *  uuid to recognise same set when adding a missing device back
         *    to an array.   This is a uuid for the device-set.
-        *  
+        *
         * For each of these we can make do with a truncated
         * or hashed uuid rather than the original, as long as
         * everyone agrees.
@@ -2050,7 +2286,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;
        }
 }
@@ -2183,16 +2419,14 @@ static int read_imsm_migr_rec(int fd, struct intel_super *super)
 
        get_dev_size(fd, NULL, &dsize);
        if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
-               fprintf(stderr,
-                       Name ": Cannot seek to anchor block: %s\n",
-                       strerror(errno));
+               pr_err("Cannot seek to anchor block: %s\n",
+                      strerror(errno));
                goto out;
        }
        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));
+               pr_err("Cannot read migr record block: %s\n",
+                      strerror(errno));
                goto out;
        }
        ret_val = 0;
@@ -2229,12 +2463,12 @@ static struct imsm_dev *imsm_get_device_during_migration(
 static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
 {
        struct mdinfo *sd;
-       struct dl *dl = NULL;
+       struct dl *dl;
        char nm[30];
        int retval = -1;
        int fd = -1;
        struct imsm_dev *dev;
-       struct imsm_map *map = NULL;
+       struct imsm_map *map;
        int slot = -1;
 
        /* find map under migration */
@@ -2309,7 +2543,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;
@@ -2319,21 +2553,18 @@ static int imsm_create_metadata_checkpoint_update(
        update_memory_size =
                sizeof(struct imsm_update_general_migration_checkpoint);
 
-       *u = calloc(1, update_memory_size);
+       *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;
 }
 
-
 static void imsm_update_metadata_locally(struct supertype *st,
                                         void *buf, int len);
 
@@ -2358,7 +2589,7 @@ static int write_imsm_migr_rec(struct supertype *st)
        int len;
        struct imsm_update_general_migration_checkpoint *u;
        struct imsm_dev *dev;
-       struct imsm_map *map = NULL;
+       struct imsm_map *map;
 
        /* find map under migration */
        dev = imsm_get_device_during_migration(super);
@@ -2389,16 +2620,14 @@ static int write_imsm_migr_rec(struct supertype *st)
                        continue;
                get_dev_size(fd, NULL, &dsize);
                if (lseek64(fd, dsize - MIGR_REC_POSITION, SEEK_SET) < 0) {
-                       fprintf(stderr,
-                               Name ": Cannot seek to anchor block: %s\n",
-                               strerror(errno));
+                       pr_err("Cannot seek to anchor block: %s\n",
+                              strerror(errno));
                        goto out;
                }
                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));
+                       pr_err("Cannot write migr record block: %s\n",
+                              strerror(errno));
                        goto out;
                }
                close(fd);
@@ -2466,9 +2695,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);
 
@@ -2476,7 +2703,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);
        }
 
@@ -2492,7 +2719,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
        struct imsm_map *prev_map = get_imsm_map(dev, MAP_1);
        struct imsm_map *map_to_analyse = map;
        struct dl *dl;
-       char *devname;
        int map_disks = info->array.raid_disks;
 
        memset(info, 0, sizeof(*info));
@@ -2617,8 +2843,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
 
                        info->reshape_progress = blocks_per_unit * units;
 
-                       dprintf("IMSM: General Migration checkpoint : %llu "
-                              "(%llu) -> read reshape progress : %llu\n",
+                       dprintf("IMSM: General Migration checkpoint : %llu (%llu) -> read reshape progress : %llu\n",
                                (unsigned long long)units,
                                (unsigned long long)blocks_per_unit,
                                info->reshape_progress);
@@ -2654,11 +2879,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
 
        info->array.major_version = -1;
        info->array.minor_version = -2;
-       devname = devnum2devname(st->container_dev);
-       *info->text_version = '\0';
-       if (devname)
-               sprintf(info->text_version, "/%s/%d", devname, info->container_member);
-       free(devname);
+       sprintf(info->text_version, "/%s/%d", st->container_devnm, info->container_member);
        info->safe_mode_delay = 4000;  /* 4 secs like the Matrix driver */
        uuid_from_super_imsm(st, info->uuid);
 
@@ -2683,7 +2904,6 @@ 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)
 {
@@ -2734,7 +2954,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
        info->array.level         = LEVEL_CONTAINER;
        info->array.layout        = 0;
        info->array.md_minor      = -1;
-       info->array.ctime         = 0; /* N/A for imsm */ 
+       info->array.ctime         = 0; /* N/A for imsm */
        info->array.utime         = 0;
        info->array.chunk_size    = 0;
 
@@ -2802,7 +3022,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) {
@@ -2841,7 +3061,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
  * for each disk in array */
 struct mdinfo *getinfo_super_disks_imsm(struct supertype *st)
 {
-       struct mdinfo *mddev = NULL;
+       struct mdinfo *mddev;
        struct intel_super *super = st->sb;
        struct imsm_disk *disk;
        int count = 0;
@@ -2849,23 +3069,11 @@ struct mdinfo *getinfo_super_disks_imsm(struct supertype *st)
        if (!super || !super->disks)
                return NULL;
        dl = super->disks;
-       mddev = malloc(sizeof(*mddev));
-       if (!mddev) {
-               fprintf(stderr, Name ": Failed to allocate memory.\n");
-               return NULL;
-       }
-       memset(mddev, 0, sizeof(*mddev));
+       mddev = xcalloc(1, sizeof(*mddev));
        while (dl) {
                struct mdinfo *tmp;
                disk = &dl->disk;
-               tmp = malloc(sizeof(*tmp));
-               if (!tmp) {
-                       fprintf(stderr, Name ": Failed to allocate memory.\n");
-                       if (mddev)
-                               sysfs_free(mddev);
-                       return NULL;
-               }
-               memset(tmp, 0, sizeof(*tmp));
+               tmp = xcalloc(1, sizeof(*tmp));
                if (mddev->devs)
                        tmp->next = mddev->devs;
                mddev->devs = tmp;
@@ -2971,7 +3179,8 @@ static size_t disks_to_mpb_size(int disks)
        return size;
 }
 
-static __u64 avail_size_imsm(struct supertype *st, __u64 devsize)
+static __u64 avail_size_imsm(struct supertype *st, __u64 devsize,
+                            unsigned long long data_offset)
 {
        if (devsize < (MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS))
                return 0;
@@ -3008,21 +3217,27 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
        struct intel_super *first = st->sb;
        struct intel_super *sec = tst->sb;
 
-        if (!first) {
-                st->sb = tst->sb;
-                tst->sb = NULL;
-                return 0;
-        }
+       if (!first) {
+               st->sb = tst->sb;
+               tst->sb = NULL;
+               return 0;
+       }
        /* in platform dependent environment test if the disks
         * 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 ||
-                   (first->hba->type != sec->hba->type))  {
+       if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) {
+               if (first->hba->type != sec->hba->type) {
+                       fprintf(stderr,
+                               "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 does not match %s != %s\n",
-                               first->hba ? get_sys_dev_type(first->hba->type) : NULL,
-                               sec->hba ? get_sys_dev_type(sec->hba->type) : NULL);
+                               "HBAs of devices do not match %s != %s\n",
+                               first->hba->pci_id, sec->hba->pci_id);
                        return 3;
                }
        }
@@ -3053,7 +3268,6 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
 
        }
 
-
        /* if 'first' is a spare promote it to a populated mpb with sec's
         * family number
         */
@@ -3067,14 +3281,8 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
                 * fails here we don't associate the spare
                 */
                for (i = 0; i < sec->anchor->num_raid_devs; i++) {
-                       dv = malloc(sizeof(*dv));
-                       if (!dv)
-                               break;
-                       dev = malloc(sizeof_imsm_dev(get_imsm_dev(sec, i), 1));
-                       if (!dev) {
-                               free(dv);
-                               break;
-                       }
+                       dv = xmalloc(sizeof(*dv));
+                       dev = xmalloc(sizeof_imsm_dev(get_imsm_dev(sec, i), 1));
                        dv->dev = dev;
                        dv->index = i;
                        dv->next = first->devlist;
@@ -3083,7 +3291,7 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst)
                if (i < sec->anchor->num_raid_devs) {
                        /* allocation failure */
                        free_devlist(first);
-                       fprintf(stderr, "imsm: failed to associate spare\n"); 
+                       pr_err("imsm: failed to associate spare\n");
                        return 3;
                }
                first->anchor->num_raid_devs = sec->anchor->num_raid_devs;
@@ -3149,18 +3357,16 @@ static int imsm_read_serial(int fd, char *devname,
 
        if (rv != 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to retrieve serial for %s\n",
-                               devname);
+                       pr_err("Failed to retrieve serial for %s\n",
+                              devname);
                return rv;
        }
 
        rsp_len = scsi_serial[3];
        if (!rsp_len) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to retrieve serial for %s\n",
-                               devname);
+                       pr_err("Failed to retrieve serial for %s\n",
+                              devname);
                return 2;
        }
        rsp_buf = (char *) &scsi_serial[4];
@@ -3249,14 +3455,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
        if (rv != 0)
                return 2;
 
-       dl = calloc(1, sizeof(*dl));
-       if (!dl) {
-               if (devname)
-                       fprintf(stderr,
-                               Name ": failed to allocate disk buffer for %s\n",
-                               devname);
-               return 2;
-       }
+       dl = xcalloc(1, sizeof(*dl));
 
        fstat(fd, &stb);
        dl->major = major(stb.st_rdev);
@@ -3270,9 +3469,9 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
        dl->e = NULL;
        fd2devname(fd, name);
        if (devname)
-               dl->devname = strdup(devname);
+               dl->devname = xstrdup(devname);
        else
-               dl->devname = strdup(name);
+               dl->devname = xstrdup(name);
 
        /* look up this disk's index in the current anchor */
        disk = __serial_to_disk(dl->serial, super->anchor, &dl->index);
@@ -3399,18 +3598,12 @@ static int parse_raid_devices(struct intel_super *super)
                if (len_migr > len)
                        space_needed += len_migr - len;
 
-               dv = malloc(sizeof(*dv));
-               if (!dv)
-                       return 1;
+               dv = xmalloc(sizeof(*dv));
                if (max_len < len_migr)
                        max_len = len_migr;
                if (max_len > len_migr)
                        space_needed += max_len - len_migr;
-               dev_new = malloc(max_len);
-               if (!dev_new) {
-                       free(dv);
-                       return 1;
-               }
+               dev_new = xmalloc(max_len);
                imsm_copy_dev(dev_new, dev_iter);
                dv->dev = dev_new;
                dv->index = i;
@@ -3446,7 +3639,7 @@ struct bbm_log *__get_imsm_bbm_log(struct imsm_super *mpb)
        if (__le32_to_cpu(mpb->bbm_log_size)) {
                ptr = mpb;
                ptr += mpb->mpb_size - __le32_to_cpu(mpb->bbm_log_size);
-       } 
+       }
 
        return ptr;
 }
@@ -3505,40 +3698,34 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        get_dev_size(fd, NULL, &dsize);
        if (dsize < 1024) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": %s: device to small for imsm\n",
-                               devname);
+                       pr_err("%s: device to small for imsm\n",
+                              devname);
                return 1;
        }
 
        if (lseek64(fd, dsize - (512 * 2), SEEK_SET) < 0) {
                if (devname)
-                       fprintf(stderr, Name
-                               ": Cannot seek to anchor block on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot seek to anchor block on %s: %s\n",
+                              devname, strerror(errno));
                return 1;
        }
 
        if (posix_memalign((void**)&anchor, 512, 512) != 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to allocate imsm anchor buffer"
-                               " on %s\n", devname);
+                       pr_err("Failed to allocate imsm anchor buffer on %s\n", devname);
                return 1;
        }
        if (read(fd, anchor, 512) != 512) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Cannot read anchor block on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot read anchor block on %s: %s\n",
+                              devname, strerror(errno));
                free(anchor);
                return 1;
        }
 
        if (strncmp((char *) anchor->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": no IMSM anchor on %s\n", devname);
+                       pr_err("no IMSM anchor on %s\n", devname);
                free(anchor);
                return 2;
        }
@@ -3551,9 +3738,8 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        super->len = ROUND_UP(anchor->mpb_size, 512);
        if (posix_memalign(&super->buf, 512, super->len) != 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": unable to allocate %zu byte mpb buffer\n",
-                               super->len);
+                       pr_err("unable to allocate %zu byte mpb buffer\n",
+                              super->len);
                free(anchor);
                return 2;
        }
@@ -3563,8 +3749,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) {
-               fprintf(stderr, Name
-                       ": %s could not allocate migr_rec buffer\n", __func__);
+               pr_err("could not allocate migr_rec buffer\n");
                free(super->buf);
                return 2;
        }
@@ -3574,11 +3759,10 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
                check_sum = __gen_imsm_checksum(super->anchor);
                if (check_sum != __le32_to_cpu(super->anchor->check_sum)) {
                        if (devname)
-                               fprintf(stderr,
-                                       Name ": IMSM checksum %x != %x on %s\n",
-                                       check_sum,
-                                       __le32_to_cpu(super->anchor->check_sum),
-                                       devname);
+                               pr_err("IMSM checksum %x != %x on %s\n",
+                                      check_sum,
+                                      __le32_to_cpu(super->anchor->check_sum),
+                                      devname);
                        return 2;
                }
 
@@ -3588,27 +3772,24 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        /* read the extended mpb */
        if (lseek64(fd, dsize - (512 * (2 + sectors)), SEEK_SET) < 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Cannot seek to extended mpb on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot seek to extended mpb on %s: %s\n",
+                              devname, strerror(errno));
                return 1;
        }
 
        if ((unsigned)read(fd, super->buf + 512, super->len - 512) != super->len - 512) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Cannot read extended mpb on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot read extended mpb on %s: %s\n",
+                              devname, strerror(errno));
                return 2;
        }
 
        check_sum = __gen_imsm_checksum(super->anchor);
        if (check_sum != __le32_to_cpu(super->anchor->check_sum)) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": IMSM checksum %x != %x on %s\n",
-                               check_sum, __le32_to_cpu(super->anchor->check_sum),
-                               devname);
+                       pr_err("IMSM checksum %x != %x on %s\n",
+                              check_sum, __le32_to_cpu(super->anchor->check_sum),
+                              devname);
                return 3;
        }
 
@@ -3747,13 +3928,10 @@ static void free_super_imsm(struct supertype *st)
 
 static struct intel_super *alloc_super(void)
 {
-       struct intel_super *super = malloc(sizeof(*super));
+       struct intel_super *super = xcalloc(1, sizeof(*super));
 
-       if (super) {
-               memset(super, 0, sizeof(*super));
-               super->current_vol = -1;
-               super->create_offset = ~((unsigned long long) 0);
-       }
+       super->current_vol = -1;
+       super->create_offset = ~((unsigned long long) 0);
        return super;
 }
 
@@ -3773,9 +3951,8 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
        hba_name = find_disk_attached_hba(fd, NULL);
        if (!hba_name) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": %s is not attached to Intel(R) RAID controller.\n",
-                               devname);
+                       pr_err("%s is not attached to Intel(R) RAID controller.\n",
+                              devname);
                return 1;
        }
        rv = attach_hba_to_super(super, hba_name);
@@ -3783,14 +3960,14 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                if (devname) {
                        struct intel_hba *hba = super->hba;
 
-                       fprintf(stderr, Name ": %s is attached to Intel(R) %s RAID "
-                               "controller (%s),\n"
-                               "    but the container is assigned to Intel(R) "
-                               "%s RAID controller (",
+                       pr_err("%s is attached to Intel(R) %s %s (%s),\n"
+                               "    but the container is assigned to Intel(R) %s %s (",
                                devname,
-                               hba_name->path,
+                               get_sys_dev_type(hba_name->type),
+                               hba_name->type == SYS_DEV_VMD ? "domain" : "RAID controller",
                                hba_name->pci_id ? : "Err!",
-                               get_sys_dev_type(hba_name->type));
+                               get_sys_dev_type(super->hba->type),
+                               hba->type == SYS_DEV_VMD ? "domain" : "RAID controller");
 
                        while (hba) {
                                fprintf(stderr, "%s", hba->pci_id ? : "Err!");
@@ -3798,18 +3975,16 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                                        fprintf(stderr, ", ");
                                hba = hba->next;
                        }
-
                        fprintf(stderr, ").\n"
-                               "    Mixing devices attached to different controllers "
-                               "is not allowed.\n");
+                               "    Mixing devices attached to different %s is not allowed.\n",
+                               hba_name->type == SYS_DEV_VMD ? "VMD domains" : "controllers");
                }
-               free_sys_dev(&hba_name);
                return 2;
        }
-       super->orom = find_imsm_capability(hba_name->type);
-       free_sys_dev(&hba_name);
+       super->orom = find_imsm_capability(hba_name);
        if (!super->orom)
                return 3;
+
        return 0;
 }
 
@@ -3830,13 +4005,11 @@ static int find_missing(struct intel_super *super)
                if (dl)
                        continue;
 
-               dl = malloc(sizeof(*dl));
-               if (!dl)
-                       return 1;
+               dl = xmalloc(sizeof(*dl));
                dl->major = 0;
                dl->minor = 0;
                dl->fd = -1;
-               dl->devname = strdup("missing");
+               dl->devname = xstrdup("missing");
                dl->index = i;
                serialcpy(dl->serial, disk->serial);
                dl->disk = *disk;
@@ -3876,8 +4049,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);
@@ -3894,8 +4067,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);
@@ -3923,8 +4096,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);
@@ -3951,9 +4124,7 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size,
                            is_failed(&idisk->disk))
                                idisk->disk.status &= ~(SPARE_DISK);
                } else {
-                       idisk = calloc(1, sizeof(*idisk));
-                       if (!idisk)
-                               return -1;
+                       idisk = xcalloc(1, sizeof(*idisk));
                        idisk->owner = IMSM_UNKNOWN_OWNER;
                        idisk->disk = *disk;
                        idisk->next = *disk_list;
@@ -3985,12 +4156,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;
                }
@@ -4008,7 +4179,7 @@ static void show_conflicts(__u32 family_num, struct intel_super *super_list)
        for (s = super_list; s; s = s->next) {
                if (family_num != s->anchor->family_num)
                        continue;
-               fprintf(stderr, "Conflict, offlining family %#x on '%s'\n",
+               pr_err("Conflict, offlining family %#x on '%s'\n",
                        __le32_to_cpu(family_num), s->disks->devname);
        }
 }
@@ -4046,8 +4217,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;
@@ -4094,8 +4265,7 @@ imsm_thunderdome(struct intel_super **super_list, int len)
        champion = s;
 
        if (conflict)
-               fprintf(stderr, "Chose family %#x on '%s', "
-                       "assemble conflicts to new container with '--update=uuid'\n",
+               pr_err("Chose family %#x on '%s', assemble conflicts to new container with '--update=uuid'\n",
                        __le32_to_cpu(s->anchor->family_num), s->disks->devname);
 
        /* collect all dl's onto 'champion', and update them to
@@ -4108,6 +4278,8 @@ imsm_thunderdome(struct intel_super **super_list, int len)
                if (s == champion)
                        continue;
 
+               mpb->attributes |= s->anchor->attributes & MPB_ATTRIB_2TB_DISK;
+
                for (i = 0; i < mpb->num_disks; i++) {
                        struct imsm_disk *disk;
 
@@ -4165,16 +4337,14 @@ imsm_thunderdome(struct intel_super **super_list, int len)
        return champion;
 }
 
-
 static int
 get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd);
-static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+static int get_super_block(struct intel_super **super_list, char *devnm, char *devname,
                           int major, int minor, int keep_fd);
 static int
 get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
                        int *max, int keep_fd);
 
-
 static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
                               char *devname, struct md_list *devlist,
                               int keep_fd)
@@ -4217,7 +4387,7 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
 
        /* Check migration compatibility */
        if ((err == 0) && (check_mpb_migr_compatibility(super) != 0)) {
-               fprintf(stderr, Name ": Unsupported migration detected");
+               pr_err("Unsupported migration detected");
                if (devname)
                        fprintf(stderr, " on %s\n", devname);
                else
@@ -4237,15 +4407,14 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
                free_imsm(s);
        }
 
-
        if (err)
                return err;
 
        *sbp = super;
        if (fd >= 0)
-               st->container_dev = fd2devnum(fd);
+               strcpy(st->container_devnm, fd2devnm(fd));
        else
-               st->container_dev = NoMdDev;
+               st->container_devnm[0] = 0;
        if (err == 0 && st->ss == NULL) {
                st->ss = &super_imsm;
                st->minor_version = 0;
@@ -4254,7 +4423,6 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
        return 0;
 }
 
-
 static int
 get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
                        int *max, int keep_fd)
@@ -4270,7 +4438,7 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list
                        int lmax = 0;
                        int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL);
                        if (fd < 0) {
-                               fprintf(stderr, Name ": cannot open device %s: %s\n",
+                               pr_err("cannot open device %s: %s\n",
                                        tmpdev->devname, strerror(errno));
                                err = 8;
                                goto error;
@@ -4288,7 +4456,7 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list
                        int major = major(tmpdev->st_rdev);
                        int minor = minor(tmpdev->st_rdev);
                        err = get_super_block(super_list,
-                                             -1,
+                                             NULL,
                                              tmpdev->devname,
                                              major, minor,
                                              keep_fd);
@@ -4304,13 +4472,12 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list
        return err;
 }
 
-static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+static int get_super_block(struct intel_super **super_list, char *devnm, char *devname,
                           int major, int minor, int keep_fd)
 {
-       struct intel_super*s = NULL;
+       struct intel_super *s;
        char nm[32];
        int dfd = -1;
-       int rv;
        int err = 0;
        int retry;
 
@@ -4327,17 +4494,11 @@ static int get_super_block(struct intel_super **super_list, int devnum, char *de
                goto error;
        }
 
-       rv = find_intel_hba_capability(dfd, s, devname);
-       /* no orom/efi or non-intel hba of the disk */
-       if (rv != 0) {
-               err = 4;
-               goto error;
-       }
-
+       find_intel_hba_capability(dfd, s, devname);
        err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
 
        /* retry the load if we might have raced against mdmon */
-       if (err == 3 && (devnum != -1) && mdmon_running(devnum))
+       if (err == 3 && devnm && mdmon_running(devnm))
                for (retry = 0; retry < 3; retry++) {
                        usleep(3000);
                        err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
@@ -4351,7 +4512,7 @@ static int get_super_block(struct intel_super **super_list, int devnum, char *de
        } else {
                if (s)
                        free(s);
-               if (dfd)
+               if (dfd >= 0)
                        close(dfd);
        }
        if ((dfd >= 0) && (!keep_fd))
@@ -4364,11 +4525,11 @@ static int
 get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd)
 {
        struct mdinfo *sra;
-       int devnum;
+       char *devnm;
        struct mdinfo *sd;
        int err = 0;
        int i = 0;
-       sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
+       sra = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
        if (!sra)
                return 1;
 
@@ -4379,9 +4540,9 @@ get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int
                goto error;
        }
        /* load all mpbs */
-       devnum = fd2devnum(fd);
+       devnm = fd2devnm(fd);
        for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
-               if (get_super_block(super_list, devnum, devname,
+               if (get_super_block(super_list, devnm, devname,
                                    sd->disk.major, sd->disk.minor, keep_fd) != 0) {
                        err = 7;
                        goto error;
@@ -4403,6 +4564,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
 {
        struct intel_super *super;
        int rv;
+       int retry;
 
        if (test_partition(fd))
                /* IMSM not allowed on partitions */
@@ -4411,12 +4573,6 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
        free_super_imsm(st);
 
        super = alloc_super();
-       if (!super) {
-               fprintf(stderr,
-                       Name ": malloc of %zu failed.\n",
-                       sizeof(*super));
-               return 1;
-       }
        /* Load hba and capabilities if they exist.
         * But do not preclude loading metadata in case capabilities or hba are
         * non-compliant and ignore_hw_compat is set.
@@ -4425,18 +4581,35 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
        /* no orom/efi or non-intel hba of the disk */
        if ((rv != 0) && (st->ignore_hw_compat == 0)) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": No OROM/EFI properties for %s\n", devname);
+                       pr_err("No OROM/EFI properties for %s\n", devname);
                free_imsm(super);
                return 2;
        }
        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 = NULL;
+               char *name = fd2kname(fd);
+
+               if (name)
+                       mdstat = mdstat_by_component(name);
+
+               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)
-                       fprintf(stderr,
-                               Name ": Failed to load all information "
-                               "sections on %s\n", devname);
+                       pr_err("Failed to load all information sections on %s\n", devname);
                free_imsm(super);
                return rv;
        }
@@ -4452,8 +4625,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
        if (load_imsm_migr_rec(super, NULL) == 0) {
                /* Check for unsupported migration features */
                if (check_mpb_migr_compatibility(super) != 0) {
-                       fprintf(stderr,
-                               Name ": Unsupported migration detected");
+                       pr_err("Unsupported migration detected");
                        if (devname)
                                fprintf(stderr, " on %s\n", devname);
                        else
@@ -4547,14 +4719,15 @@ static int check_name(struct intel_super *super, char *name, int quiet)
        }
 
        if (reason && !quiet)
-               fprintf(stderr, Name ": imsm volume name %s\n", reason);
+               pr_err("imsm volume name %s\n", reason);
 
        return !reason;
 }
 
 static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                                  unsigned long long size, char *name,
-                                 char *homehost, int *uuid)
+                                 char *homehost, int *uuid,
+                                 long long data_offset)
 {
        /* We are creating a volume inside a pre-existing container.
         * so st->sb is already set.
@@ -4572,8 +4745,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        unsigned long long num_data_stripes;
 
        if (super->orom && mpb->num_raid_devs >= super->orom->vpa) {
-               fprintf(stderr, Name": This imsm-container already has the "
-                       "maximum of %d volumes\n", super->orom->vpa);
+               pr_err("This imsm-container already has the maximum of %d volumes\n", super->orom->vpa);
                return 0;
        }
 
@@ -4585,14 +4757,12 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                size_t size_round = ROUND_UP(size_new, 512);
 
                if (posix_memalign(&mpb_new, 512, size_round) != 0) {
-                       fprintf(stderr, Name": could not allocate new mpb\n");
+                       pr_err("could not allocate new mpb\n");
                        return 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__);
+                       pr_err("could not allocate migr_rec buffer\n");
                        free(super->buf);
                        free(super);
                        free(mpb_new);
@@ -4636,25 +4806,15 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                for (d = super->missing; d; d = d->next)
                        missing++;
                if (info->failed_disks > missing) {
-                       fprintf(stderr, Name": unable to add 'missing' disk to container\n");
+                       pr_err("unable to add 'missing' disk to container\n");
                        return 0;
                }
        }
 
        if (!check_name(super, name, 0))
                return 0;
-       dv = malloc(sizeof(*dv));
-       if (!dv) {
-               fprintf(stderr, Name ": failed to allocate device list entry\n");
-               return 0;
-       }
-       dev = calloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
-       if (!dev) {
-               free(dv);
-               fprintf(stderr, Name": could not allocate raid device\n");
-               return 0;
-       }
-
+       dv = xmalloc(sizeof(*dv));
+       dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
        strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
        array_blocks = calc_array_size(info->level, info->raid_disks,
                                               info->layout, info->chunk_size,
@@ -4676,7 +4836,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
        map->failed_disk_num = ~0;
        if (info->level > 0)
-               map->map_state = IMSM_T_STATE_UNINITIALIZED;
+               map->map_state = (info->state ? IMSM_T_STATE_NORMAL
+                                 : IMSM_T_STATE_UNINITIALIZED);
        else
                map->map_state = info->failed_disks ? IMSM_T_STATE_FAILED :
                                                      IMSM_T_STATE_NORMAL;
@@ -4685,8 +4846,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        if (info->level == 1 && info->raid_disks > 2) {
                free(dev);
                free(dv);
-               fprintf(stderr, Name": imsm does not support more than 2 disks"
-                               "in a raid1 volume\n");
+               pr_err("imsm does not support more than 2 disksin a raid1 volume\n");
                return 0;
        }
 
@@ -4723,7 +4883,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
 
 static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
                           unsigned long long size, char *name,
-                          char *homehost, int *uuid)
+                          char *homehost, int *uuid,
+                          unsigned long long data_offset)
 {
        /* This is primarily called by Create when creating a new array.
         * We will then get add_to_super called for each component, and then
@@ -4738,8 +4899,14 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
        size_t mpb_size;
        char *version;
 
+       if (data_offset != INVALID_SECTORS) {
+               pr_err("data-offset not supported by imsm\n");
+               return 0;
+       }
+
        if (st->sb)
-               return init_super_imsm_volume(st, info, size, name, homehost, uuid);
+               return init_super_imsm_volume(st, info, size, name, homehost, uuid,
+                                             data_offset);
 
        if (info)
                mpb_size = disks_to_mpb_size(info->nr_disks);
@@ -4752,13 +4919,11 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
                super = NULL;
        }
        if (!super) {
-               fprintf(stderr, Name
-                       ": %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) {
-               fprintf(stderr, Name
-                       ": %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;
@@ -4799,7 +4964,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        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",
+               pr_err("%s: Cannot add spare devices to IMSM volume\n",
                        devname);
                return 1;
        }
@@ -4819,7 +4984,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        }
 
        if (!dl) {
-               fprintf(stderr, Name ": %s is not a member of the same container\n", devname);
+               pr_err("%s is not a member of the same container\n", devname);
                return 1;
        }
 
@@ -4832,7 +4997,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        slot = get_imsm_disk_slot(map, dl->index);
        if (slot >= 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",
+               pr_err("%s has been included in this array twice\n",
                        devname);
                return 1;
        }
@@ -4888,7 +5053,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
 
                _disk = __get_imsm_disk(mpb, dl->index);
                if (!_dev || !_disk) {
-                       fprintf(stderr, Name ": BUG mpb setup error\n");
+                       pr_err("BUG mpb setup error\n");
                        return 1;
                }
                *_dev = *dev;
@@ -4935,7 +5100,8 @@ int mark_spare(struct dl *disk)
 }
 
 static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
-                            int fd, char *devname)
+                            int fd, char *devname,
+                            unsigned long long data_offset)
 {
        struct intel_super *super = st->sb;
        struct dl *dd;
@@ -4961,28 +5127,29 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
                return add_to_super_imsm_volume(st, dk, fd, devname);
 
        fstat(fd, &stb);
-       dd = malloc(sizeof(*dd));
-       if (!dd) {
-               fprintf(stderr,
-                       Name ": malloc failed %s:%d.\n", __func__, __LINE__);
-               return 1;
-       }
-       memset(dd, 0, sizeof(*dd));
+       dd = xcalloc(sizeof(*dd), 1);
        dd->major = major(stb.st_rdev);
        dd->minor = minor(stb.st_rdev);
-       dd->devname = devname ? strdup(devname) : NULL;
+       dd->devname = devname ? xstrdup(devname) : NULL;
        dd->fd = fd;
        dd->e = NULL;
        dd->action = DISK_ADD;
        rv = imsm_read_serial(fd, devname, dd->serial);
        if (rv) {
-               fprintf(stderr,
-                       Name ": failed to retrieve scsi serial, aborting\n");
+               pr_err("failed to retrieve scsi serial, aborting\n");
                free(dd);
                abort();
        }
 
        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);
@@ -5008,7 +5175,6 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        return 0;
 }
 
-
 static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
 {
        struct intel_super *super = st->sb;
@@ -5019,18 +5185,10 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
         * is prepared.
         */
        if (!st->update_tail) {
-               fprintf(stderr,
-                       Name ": %s shall be used in mdmon context only"
-                       "(line %d).\n", __func__, __LINE__);
-               return 1;
-       }
-       dd = malloc(sizeof(*dd));
-       if (!dd) {
-               fprintf(stderr,
-                       Name ": malloc failed %s:%d.\n", __func__, __LINE__);
+               pr_err("shall be used in mdmon context only\n");
                return 1;
        }
-       memset(dd, 0, sizeof(*dd));
+       dd = xcalloc(1, sizeof(*dd));
        dd->major = dk->major;
        dd->minor = dk->minor;
        dd->fd = -1;
@@ -5040,7 +5198,6 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
        dd->next = super->disk_mgmt_list;
        super->disk_mgmt_list = dd;
 
-
        return 0;
 }
 
@@ -5061,13 +5218,13 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
        __u32 sum;
        struct dl *d;
 
-       spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super)),
-       spare->generation_num = __cpu_to_le32(1UL),
+       spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super));
+       spare->generation_num = __cpu_to_le32(1UL);
        spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
-       spare->num_disks = 1,
-       spare->num_raid_devs = 0,
-       spare->cache_size = mpb->cache_size,
-       spare->pwr_cycle_count = __cpu_to_le32(1),
+       spare->num_disks = 1;
+       spare->num_raid_devs = 0;
+       spare->cache_size = mpb->cache_size;
+       spare->pwr_cycle_count = __cpu_to_le32(1);
 
        snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH,
                 MPB_SIGNATURE MPB_VERSION_RAID0);
@@ -5087,8 +5244,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)) {
-                       fprintf(stderr, "%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) {
@@ -5181,8 +5338,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) {
@@ -5197,7 +5354,6 @@ static int write_super_imsm(struct supertype *st, int doclose)
        return 0;
 }
 
-
 static int create_array(struct supertype *st, int dev_idx)
 {
        size_t len;
@@ -5211,13 +5367,7 @@ static int create_array(struct supertype *st, int dev_idx)
 
        len = sizeof(*u) - sizeof(*dev) + sizeof_imsm_dev(dev, 0) +
              sizeof(*inf) * map->num_members;
-       u = malloc(len);
-       if (!u) {
-               fprintf(stderr, "%s: failed to allocate update buffer\n",
-                       __func__);
-               return 1;
-       }
-
+       u = xmalloc(len);
        u->type = update_create_array;
        u->dev_idx = dev_idx;
        imsm_copy_dev(&u->dev, dev);
@@ -5226,6 +5376,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);
@@ -5243,13 +5395,7 @@ static int mgmt_disk(struct supertype *st)
                return 0;
 
        len = sizeof(*u);
-       u = malloc(len);
-       if (!u) {
-               fprintf(stderr, "%s: failed to allocate update buffer\n",
-                       __func__);
-               return 1;
-       }
-
+       u = xmalloc(len);
        u->type = update_add_remove_disk;
        append_metadata_update(st, u, len);
 
@@ -5282,7 +5428,7 @@ static int write_init_super_imsm(struct supertype *st)
        } else {
                struct dl *d;
                for (d = super->disks; d; d = d->next)
-                       Kill(d->devname, NULL, 0, 1, 1);
+                       Kill(d->devname, NULL, 0, -1, 1);
                return write_super_imsm(st, 1);
        }
 }
@@ -5311,13 +5457,15 @@ static int imsm_bbm_log_size(struct imsm_super *mpb)
 #ifndef MDASSEMBLE
 static int validate_geometry_imsm_container(struct supertype *st, int level,
                                            int layout, int raiddisks, int chunk,
-                                           unsigned long long size, char *dev,
+                                           unsigned long long size,
+                                           unsigned long long data_offset,
+                                           char *dev,
                                            unsigned long long *freesize,
                                            int verbose)
 {
        int fd;
        unsigned long long ldsize;
-       struct intel_super *super=NULL;
+       struct intel_super *super;
        int rv = 0;
 
        if (level != LEVEL_CONTAINER)
@@ -5327,8 +5475,8 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
 
        fd = open(dev, O_RDONLY|O_EXCL, 0);
        if (fd < 0) {
-               if (verbose)
-                       fprintf(stderr, Name ": imsm: Cannot open %s: %s\n",
+               if (verbose > 0)
+                       pr_err("imsm: Cannot open %s: %s\n",
                                dev, strerror(errno));
                return 0;
        }
@@ -5341,20 +5489,12 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
         * note that there is no fd for the disks in array.
         */
        super = alloc_super();
-       if (!super) {
-               fprintf(stderr,
-                       Name ": malloc of %zu failed.\n",
-                       sizeof(*super));
-               close(fd);
-               return 0;
-       }
-
-       rv = find_intel_hba_capability(fd, super, verbose ? dev : NULL);
+       rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
        if (rv != 0) {
 #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 */
@@ -5366,8 +5506,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
        if (super->orom) {
                if (raiddisks > super->orom->tds) {
                        if (verbose)
-                               fprintf(stderr, Name ": %d exceeds maximum number of"
-                                       " platform supported disks: %d\n",
+                               pr_err("%d exceeds maximum number of platform supported disks: %d\n",
                                        raiddisks, super->orom->tds);
                        free_imsm(super);
                        return 0;
@@ -5375,13 +5514,13 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
                if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
                    (ldsize >> 9) >> 32 > 0) {
                        if (verbose)
-                               fprintf(stderr, Name ": %s exceeds maximum platform supported size\n", dev);
+                               pr_err("%s exceeds maximum platform supported size\n", dev);
                        free_imsm(super);
                        return 0;
                }
        }
 
-       *freesize = avail_size_imsm(st, ldsize >> 9);
+       *freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
        free_imsm(super);
 
        return 1;
@@ -5420,7 +5559,7 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
         * 'maxsize' given the "all disks in an array must share a common start
         * offset" constraint
         */
-       struct extent *e = calloc(sum_extents, sizeof(*e));
+       struct extent *e = xcalloc(sum_extents, sizeof(*e));
        struct dl *dl;
        int i, j;
        int start_extent;
@@ -5429,9 +5568,6 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
        unsigned long long maxsize;
        unsigned long reserve;
 
-       if (!e)
-               return 0;
-
        /* coalesce and sort all extents. also, check to see if we need to
         * reserve space between member arrays
         */
@@ -5517,16 +5653,15 @@ static int is_raid_level_supported(const struct imsm_orom *orom, int level, int
        return 0;
 }
 
-
 static int
 active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
                        int dpa, int verbose)
 {
        struct mdstat_ent *mdstat = mdstat_read(0, 0);
-       struct mdstat_ent *memb = NULL;
+       struct mdstat_ent *memb;
        int count = 0;
        int num = 0;
-       struct md_list *dv = NULL;
+       struct md_list *dv;
        int found;
 
        for (memb = mdstat ; memb ; memb = memb->next) {
@@ -5538,17 +5673,15 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
                        struct dev_member *dev = memb->members;
                        int fd = -1;
                        while(dev && (fd < 0)) {
-                               char *path = malloc(strlen(dev->name) + strlen("/dev/") + 1);
-                               if (path) {
-                                       num = sprintf(path, "%s%s", "/dev/", dev->name);
-                                       if (num > 0)
-                                               fd = open(path, O_RDONLY, 0);
-                                       if ((num <= 0) || (fd < 0)) {
-                                               pr_vrb(": Cannot open %s: %s\n",
-                                                      dev->name, strerror(errno));
-                                       }
-                                       free(path);
+                               char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1);
+                               num = sprintf(path, "%s%s", "/dev/", dev->name);
+                               if (num > 0)
+                                       fd = open(path, O_RDONLY, 0);
+                               if ((num <= 0) || (fd < 0)) {
+                                       pr_vrb("Cannot open %s: %s\n",
+                                              dev->name, strerror(errno));
                                }
+                               free(path);
                                dev = dev->next;
                        }
                        found = 0;
@@ -5557,26 +5690,19 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
                                for (vol = mdstat ; vol ; vol = vol->next) {
                                        if ((vol->active > 0) &&
                                            vol->metadata_version &&
-                                           is_container_member(vol, memb->dev)) {
+                                           is_container_member(vol, memb->devnm)) {
                                                found++;
                                                count++;
                                        }
                                }
                                if (*devlist && (found < dpa)) {
-                                 dv = calloc(1, sizeof(*dv));
-                                       if (dv == NULL)
-                                               fprintf(stderr, Name ": calloc failed\n");
-                                       else {
-                                               dv->devname = malloc(strlen(memb->dev) + strlen("/dev/") + 1);
-                                               if (dv->devname != NULL) {
-                                                       sprintf(dv->devname, "%s%s", "/dev/", memb->dev);
-                                                       dv->found = found;
-                                                       dv->used = 0;
-                                                       dv->next = *devlist;
-                                                       *devlist = dv;
-                                               } else
-                                                       free(dv);
-                                       }
+                                       dv = xcalloc(1, sizeof(*dv));
+                                       dv->devname = xmalloc(strlen(memb->devnm) + strlen("/dev/") + 1);
+                                       sprintf(dv->devname, "%s%s", "/dev/", memb->devnm);
+                                       dv->found = found;
+                                       dv->used = 0;
+                                       dv->next = *devlist;
+                                       *devlist = dv;
                                }
                        }
                        if (fd >= 0)
@@ -5593,20 +5719,11 @@ get_loop_devices(void)
 {
        int i;
        struct md_list *devlist = NULL;
-       struct md_list *dv = NULL;
+       struct md_list *dv;
 
        for(i = 0; i < 12; i++) {
-               dv = calloc(1, sizeof(*dv));
-               if (dv == NULL) {
-                       fprintf(stderr, Name ": calloc failed\n");
-                       break;
-               }
-               dv->devname = malloc(40);
-               if (dv->devname == NULL) {
-                       fprintf(stderr, Name ": malloc failed\n");
-                       free(dv);
-                       break;
-               }
+               dv = xcalloc(1, sizeof(*dv));
+               dv->devname = xmalloc(40);
                sprintf(dv->devname, "/dev/loop%d", i);
                dv->next = devlist;
                devlist = dv;
@@ -5619,7 +5736,7 @@ static struct md_list*
 get_devices(const char *hba_path)
 {
        struct md_list *devlist = NULL;
-       struct md_list *dv = NULL;
+       struct md_list *dv;
        struct dirent *ent;
        DIR *dir;
        int err = 0;
@@ -5654,25 +5771,13 @@ get_devices(const char *hba_path)
                        fd2devname(fd, buf);
                        close(fd);
                } else {
-                       fprintf(stderr, Name ": cannot open device: %s\n",
+                       pr_err("cannot open device: %s\n",
                                ent->d_name);
                        continue;
                }
 
-
-               dv = calloc(1, sizeof(*dv));
-               if (dv == NULL) {
-                       fprintf(stderr, Name ": malloc failed\n");
-                       err = 1;
-                       break;
-               }
-               dv->devname = strdup(buf);
-               if (dv->devname == NULL) {
-                       fprintf(stderr, Name ": malloc failed\n");
-                       err = 1;
-                       free(dv);
-                       break;
-               }
+               dv = xcalloc(1, sizeof(*dv));
+               dv->devname = xstrdup(buf);
                dv->next = devlist;
                devlist = dv;
        }
@@ -5684,6 +5789,7 @@ get_devices(const char *hba_path)
                        free(dv);
                }
        }
+       closedir(dir);
        return devlist;
 }
 
@@ -5693,7 +5799,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
 {
        struct md_list *tmpdev;
        int count = 0;
-       struct supertype *st = NULL;
+       struct supertype *st;
 
        /* first walk the list of devices to find a consistent set
         * that match the criterea, if that is possible.
@@ -5702,7 +5808,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
        *found = 0;
        st = match_metadata_desc_imsm("imsm");
        if (st == NULL) {
-               pr_vrb("cannot allocate memory for imsm supertype\n");
+               pr_vrb("cannot allocate memory for imsm supertype\n");
                return 0;
        }
 
@@ -5715,33 +5821,33 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                        continue;
                tst = dup_super(st);
                if (tst == NULL) {
-                       pr_vrb("cannot allocate memory for imsm supertype\n");
+                       pr_vrb("cannot allocate memory for imsm supertype\n");
                        goto err_1;
                }
                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 ||
@@ -5755,11 +5861,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;
                        }
@@ -5796,7 +5902,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;
                        }
@@ -5818,7 +5924,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++;
@@ -5826,11 +5932,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) {
@@ -5851,39 +5957,76 @@ count_volumes_list(struct md_list *devlist, char *homehost,
        return count;
 }
 
-
 static int
-count_volumes(char *hba, int dpa, int verbose)
+count_volumes(struct intel_hba *hba, int dpa, int verbose)
 {
-       struct md_list *devlist = NULL;
+       struct sys_dev *idev, *intel_devices = find_intel_devices();
        int count = 0;
-       int found = 0;;
+       const struct orom_entry *entry;
+       struct devid_list *dv, *devid_list;
 
-       devlist = get_devices(hba);
-       /* if no intel devices return zero volumes */
-       if (devlist == NULL)
+       if (!hba || !hba->path)
                return 0;
 
-       count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose);
-       dprintf(" path: %s active arrays: %d\n", hba, count);
-       if (devlist == NULL)
+       for (idev = intel_devices; idev; idev = idev->next) {
+               if (strstr(idev->path, hba->path))
+                               break;
+       }
+
+       if (!idev || !idev->dev_id)
                return 0;
-       do  {
-               found = 0;
-               count += count_volumes_list(devlist,
-                                           NULL,
-                                           verbose,
-                                           &found);
-               dprintf("found %d count: %d\n", found, count);
-       } while (found);
-
-       dprintf("path: %s total number of volumes: %d\n", hba, count);
-
-       while(devlist) {
-               struct md_list *dv = devlist;
-               devlist = devlist->next;
-               free(dv->devname);
-               free(dv);
+
+       entry = get_orom_entry_by_device_id(idev->dev_id);
+
+       if (!entry || !entry->devid_list)
+               return 0;
+
+       devid_list = entry->devid_list;
+       for (dv = devid_list; dv; dv = dv->next) {
+               struct md_list *devlist;
+               struct sys_dev *device = device_by_id(dv->devid);
+               char *hba_path;
+               int found = 0;
+
+               if (device)
+                       hba_path = device->path;
+               else
+                       return 0;
+
+               /* VMD has one orom entry for all domain, but spanning is not allowed.
+                * VMD arrays should be counted per domain (controller), so skip
+                * domains that are not the given one.
+                */
+               if ((hba->type == SYS_DEV_VMD) &&
+                  (strncmp(device->path, hba->path, strlen(device->path)) != 0))
+                       continue;
+
+               devlist = get_devices(hba_path);
+               /* if no intel devices return zero volumes */
+               if (devlist == NULL)
+                       return 0;
+
+               count += active_arrays_by_format("imsm", hba_path, &devlist, dpa, verbose);
+               dprintf("path: %s active arrays: %d\n", hba_path, count);
+               if (devlist == NULL)
+                       return 0;
+               do  {
+                       found = 0;
+                       count += count_volumes_list(devlist,
+                                                       NULL,
+                                                       verbose,
+                                                       &found);
+                       dprintf("found %d count: %d\n", found, count);
+               } while (found);
+
+               dprintf("path: %s total number of volumes: %d\n", hba_path, count);
+
+               while (devlist) {
+                       struct md_list *dv = devlist;
+                       devlist = devlist->next;
+                       free(dv->devname);
+                       free(dv);
+               }
        }
        return count;
 }
@@ -5904,52 +6047,54 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
 {
        /* check/set platform and metadata limits/defaults */
        if (super->orom && raiddisks > super->orom->dpa) {
-               pr_vrb("platform supports a maximum of %d disks per array\n",
+               pr_vrb("platform supports a maximum of %d disks per array\n",
                       super->orom->dpa);
                return 0;
        }
 
-        /* capabilities of OROM tested - copied from validate_geometry_imsm_volume */
+       /* capabilities of OROM tested - copied from validate_geometry_imsm_volume */
        if (!is_raid_level_supported(super->orom, level, raiddisks)) {
-               pr_vrb("platform does not support raid%d with %d disk%s\n",
+               pr_vrb("platform does not support raid%d with %d disk%s\n",
                        level, raiddisks, raiddisks > 1 ? "s" : "");
                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)) {
-               pr_vrb(": platform does not support a chunk size of: "
-                      "%d\n", *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;
        }
 
        if (layout != imsm_level_to_layout(level)) {
                if (level == 5)
-                       pr_vrb("imsm raid 5 only supports the left-asymmetric layout\n");
+                       pr_vrb("imsm raid 5 only supports the left-asymmetric layout\n");
                else if (level == 10)
-                       pr_vrb("imsm raid 10 only supports the n2 layout\n");
+                       pr_vrb("imsm raid 10 only supports the n2 layout\n");
                else
-                       pr_vrb("imsm unknown layout %#x for this raid level %d\n",
+                       pr_vrb("imsm unknown layout %#x for this raid level %d\n",
                                layout, level);
                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");
+               pr_vrb("platform does not support a volume size over 2TB\n");
                return 0;
        }
+
        return 1;
 }
 
-/* validate_geometry_imsm_volume - lifted from validate_geometry_ddf_bvd 
+/* validate_geometry_imsm_volume - lifted from validate_geometry_ddf_bvd
  * FIX ME add ahci details
  */
 static int validate_geometry_imsm_volume(struct supertype *st, int level,
                                         int layout, int raiddisks, int *chunk,
-                                        unsigned long long size, char *dev,
+                                        unsigned long long size,
+                                        unsigned long long data_offset,
+                                        char *dev,
                                         unsigned long long *freesize,
                                         int verbose)
 {
@@ -5969,8 +6114,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
        mpb = super->anchor;
 
        if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, size, verbose)) {
-               fprintf(stderr, Name ": RAID gemetry validation failed. "
-                       "Cannot proceed with the action(s).\n");
+               pr_err("RAID gemetry validation failed. Cannot proceed with the action(s).\n");
                return 0;
        }
        if (!dev) {
@@ -6011,9 +6155,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                }
                if (dcnt < raiddisks) {
                        if (verbose)
-                               fprintf(stderr, Name ": imsm: Not enough "
-                                       "devices with space for this array "
-                                       "(%d < %d)\n",
+                               pr_err("imsm: Not enough devices with space for this array (%d < %d)\n",
                                        dcnt, raiddisks);
                        return 0;
                }
@@ -6032,8 +6174,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
        }
        if (!dl) {
                if (verbose)
-                       fprintf(stderr, Name ": %s is not in the "
-                               "same imsm set\n", dev);
+                       pr_err("%s is not in the same imsm set\n", dev);
                return 0;
        } else if (super->orom && dl->index < 0 && mpb->num_raid_devs) {
                /* If a volume is present then the current creation attempt
@@ -6041,15 +6182,12 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                 * understand this configuration (all member disks must be
                 * members of each array in the container).
                 */
-               fprintf(stderr, Name ": %s is a spare and a volume"
-                       " is already defined for this container\n", dev);
-               fprintf(stderr, Name ": The option-rom requires all member"
-                       " disks to be a member of all volumes\n");
+               pr_err("%s is a spare and a volume is already defined for this container\n", dev);
+               pr_err("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");
+               pr_err("The option-rom requires all member disks to be a member of all volumes\n");
                return 0;
        }
 
@@ -6071,13 +6209,13 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                dl->extent_cnt = i;
        } else {
                if (verbose)
-                       fprintf(stderr, Name ": unable to determine free space for: %s\n",
+                       pr_err("unable to determine free space for: %s\n",
                                dev);
                return 0;
        }
        if (maxsize < size) {
                if (verbose)
-                       fprintf(stderr, Name ": %s not enough space (%llu < %llu)\n",
+                       pr_err("%s not enough space (%llu < %llu)\n",
                                dev, maxsize, size);
                return 0;
        }
@@ -6092,21 +6230,16 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
 
        if (!check_env("IMSM_NO_PLATFORM") &&
            mpb->num_raid_devs > 0 && size && size != maxsize) {
-               fprintf(stderr, Name ": attempting to create a second "
-                       "volume with size less then remaining space. "
-                       "Aborting...\n");
+               pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
                return 0;
        }
 
        if (maxsize < size || maxsize == 0) {
                if (verbose) {
                        if (maxsize == 0)
-                               fprintf(stderr, Name ": no free space"
-                                               " left on device. Aborting...\n");
+                               pr_err("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",
+                               pr_err("not enough space to create volume of given size (%llu < %llu). Aborting...\n",
                                                maxsize, size);
                }
                return 0;
@@ -6115,10 +6248,10 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
        *freesize = maxsize;
 
        if (super->orom) {
-               int count = count_volumes(super->hba->path,
+               int count = count_volumes(super->hba,
                                      super->orom->dpa, verbose);
                if (super->orom->vphba <= count) {
-                       pr_vrb("platform does not support more than %d raid volumes.\n",
+                       pr_vrb("platform does not support more than %d raid volumes.\n",
                               super->orom->vphba);
                        return 0;
                }
@@ -6178,7 +6311,7 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
            (super->orom && used && used != raiddisks) ||
            maxsize < minsize ||
            maxsize == 0) {
-               fprintf(stderr, Name ": not enough devices with space to create array.\n");
+               pr_err("not enough devices with space to create array.\n");
                return 0; /* No enough free spaces large enough */
        }
 
@@ -6192,9 +6325,7 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks,
        }
        if (!check_env("IMSM_NO_PLATFORM") &&
            mpb->num_raid_devs > 0 && size && size != maxsize) {
-               fprintf(stderr, Name ": attempting to create a second "
-                       "volume with size less then remaining space. "
-                       "Aborting...\n");
+               pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
                return 0;
        }
        cnt = 0;
@@ -6232,6 +6363,7 @@ static int reserve_space(struct supertype *st, int raiddisks,
 
 static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                                  int raiddisks, int *chunk, unsigned long long size,
+                                 unsigned long long data_offset,
                                  char *dev, unsigned long long *freesize,
                                  int verbose)
 {
@@ -6247,7 +6379,8 @@ 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, size,
+                                                       *chunk,
+                                                       size, data_offset,
                                                        dev, freesize,
                                                        verbose);
        }
@@ -6271,18 +6404,17 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                           created */
                        if (super->orom && freesize) {
                                int count;
-                               count = count_volumes(super->hba->path,
+                               count = count_volumes(super->hba,
                                                      super->orom->dpa, verbose);
                                if (super->orom->vphba <= count) {
-                                       pr_vrb(": platform does not support more"
-                                              " than %d raid volumes.\n",
+                                       pr_vrb("platform does not support more than %d raid volumes.\n",
                                               super->orom->vphba);
                                        return 0;
                                }
                        }
                        if (freesize)
                                return reserve_space(st, raiddisks, size,
-                                                    chunk?*chunk:0, freesize);
+                                                    *chunk, freesize);
                }
                return 1;
        }
@@ -6290,6 +6422,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                /* creating in a given container */
                return validate_geometry_imsm_volume(st, level, layout,
                                                     raiddisks, chunk, size,
+                                                    data_offset,
                                                     dev, freesize, verbose);
        }
 
@@ -6297,15 +6430,14 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
        fd = open(dev, O_RDONLY|O_EXCL, 0);
        if (fd >= 0) {
                if (verbose)
-                       fprintf(stderr,
-                               Name ": Cannot create this array on device %s\n",
-                               dev);
+                       pr_err("Cannot create this array on device %s\n",
+                              dev);
                close(fd);
                return 0;
        }
        if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) {
                if (verbose)
-                       fprintf(stderr, Name ": Cannot open %s: %s\n",
+                       pr_err("Cannot open %s: %s\n",
                                dev, strerror(errno));
                return 0;
        }
@@ -6314,11 +6446,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
        close(fd);
        if (cfd < 0) {
                if (verbose)
-                       fprintf(stderr, Name ": Cannot use %s: It is busy\n",
+                       pr_err("Cannot use %s: It is busy\n",
                                dev);
                return 0;
        }
-       sra = sysfs_read(cfd, 0, GET_VERSION);
+       sra = sysfs_read(cfd, NULL, GET_VERSION);
        if (sra && sra->array.major_version == -1 &&
            strcmp(sra->text_version, "imsm") == 0)
                is_member = 1;
@@ -6331,18 +6463,18 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
 
                if (load_super_imsm_all(st, cfd, (void **) &super, NULL, NULL, 1) == 0) {
                        st->sb = super;
-                       st->container_dev = fd2devnum(cfd);
+                       strcpy(st->container_devnm, fd2devnm(cfd));
                        close(cfd);
                        return validate_geometry_imsm_volume(st, level, layout,
                                                             raiddisks, chunk,
-                                                            size, dev,
+                                                            size, data_offset, dev,
                                                             freesize, 1)
                                ? 1 : -1;
                }
        }
 
        if (verbose)
-               fprintf(stderr, Name ": failed container membership check\n");
+               pr_err("failed container membership check\n");
 
        close(cfd);
        return 0;
@@ -6389,20 +6521,17 @@ static int kill_subarray_imsm(struct supertype *st)
                if (i < current_vol)
                        continue;
                sprintf(subarray, "%u", i);
-               if (is_subarray_active(subarray, st->devname)) {
-                       fprintf(stderr,
-                               Name ": deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
-                               current_vol, i);
+               if (is_subarray_active(subarray, st->devnm)) {
+                       pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
+                              current_vol, i);
 
                        return 2;
                }
        }
 
        if (st->update_tail) {
-               struct imsm_update_kill_array *u = malloc(sizeof(*u));
+               struct imsm_update_kill_array *u = xmalloc(sizeof(*u));
 
-               if (!u)
-                       return 2;
                u->type = update_kill_array;
                u->dev_idx = current_vol;
                append_metadata_update(st, u, sizeof(*u));
@@ -6448,9 +6577,8 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
                char *ep;
                int vol;
 
-               if (is_subarray_active(subarray, st->devname)) {
-                       fprintf(stderr,
-                               Name ": Unable to update name of active subarray\n");
+               if (is_subarray_active(subarray, st->devnm)) {
+                       pr_err("Unable to update name of active subarray\n");
                        return 2;
                }
 
@@ -6462,10 +6590,8 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
                        return 2;
 
                if (st->update_tail) {
-                       struct imsm_update_rename_array *u = malloc(sizeof(*u));
+                       struct imsm_update_rename_array *u = xmalloc(sizeof(*u));
 
-                       if (!u)
-                               return 2;
                        u->type = update_rename_array;
                        u->dev_idx = vol;
                        snprintf((char *) u->name, MAX_RAID_SERIAL_LEN, "%s", name);
@@ -6565,7 +6691,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;
        }
 
@@ -6599,18 +6725,15 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
        /* do not assemble arrays when not all attributes are supported */
        if (imsm_check_attributes(mpb->attributes) == 0) {
                sb_errors = 1;
-               fprintf(stderr, Name ": Unsupported attributes in IMSM metadata."
-                       "Arrays activation is blocked.\n");
+               pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n");
        }
 
        /* check for bad blocks */
        if (imsm_bbm_log_size(super->anchor)) {
-               fprintf(stderr, Name ": BBM log found in IMSM metadata."
-                       "Arrays activation is blocked.\n");
+               pr_err("BBM log found in IMSM metadata.Arrays activation is blocked.\n");
                sb_errors = 1;
        }
 
-
        /* count spare devices, not used in maps
         */
        for (d = super->disks; d; d = d->next)
@@ -6641,8 +6764,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                 */
                if (dev->vol.migr_state &&
                    (migr_type(dev) == MIGR_STATE_CHANGE)) {
-                       fprintf(stderr, Name ": cannot assemble volume '%.16s':"
-                               " unsupported migration in progress\n",
+                       pr_err("cannot assemble volume '%.16s': unsupported migration in progress\n",
                                dev->volume);
                        continue;
                }
@@ -6650,12 +6772,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                 * OROM/EFI
                 */
 
-               this = malloc(sizeof(*this));
-               if (!this) {
-                       fprintf(stderr, Name ": failed to allocate %zu bytes\n",
-                               sizeof(*this));
-                       break;
-               }
+               this = xmalloc(sizeof(*this));
 
                super->current_vol = i;
                getinfo_super_imsm_volume(st, this, NULL);
@@ -6669,8 +6786,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                                                 map->num_members, /* raid disks */
                                                 &chunk, join_u32(dev->size_low, dev->size_high),
                                                 1 /* verbose */)) {
-                       fprintf(stderr, Name ": IMSM RAID geometry validation"
-                               " failed.  Array %s activation is blocked.\n",
+                       pr_err("IMSM RAID geometry validation failed.  Array %s activation is blocked.\n",
                                dev->volume);
                        this->array.state |=
                          (1<<MD_SB_BLOCK_CONTAINER_RESHAPE) |
@@ -6707,7 +6823,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                        if (ord & IMSM_ORD_REBUILD)
                                recovery_start = 0;
 
-                       /* 
+                       /*
                         * if we skip some disks the array will be assmebled degraded;
                         * reset resync start to avoid a dirty-degraded
                         * situation when performing the intial sync
@@ -6719,21 +6835,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                        if (skip)
                                continue;
 
-                       info_d = calloc(1, sizeof(*info_d));
-                       if (!info_d) {
-                               fprintf(stderr, Name ": failed to allocate disk"
-                                       " for volume %.16s\n", dev->volume);
-                               info_d = this->devs;
-                               while (info_d) {
-                                       struct mdinfo *d = info_d->next;
-
-                                       free(info_d);
-                                       info_d = d;
-                               }
-                               free(this);
-                               this = rest;
-                               break;
-                       }
+                       info_d = xcalloc(1, sizeof(*info_d));
                        info_d->next = this->devs;
                        this->devs = info_d;
 
@@ -6775,7 +6877,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
        return rest;
 }
 
-
 static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
                                int failed, int look_in_map)
 {
@@ -6784,7 +6885,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
        map = get_imsm_map(dev, look_in_map);
 
        if (!failed)
-               return map->map_state == IMSM_T_STATE_UNINITIALIZED ? 
+               return map->map_state == IMSM_T_STATE_UNINITIALIZED ?
                        IMSM_T_STATE_UNINITIALIZED : IMSM_T_STATE_NORMAL;
 
        switch (get_imsm_raid_level(map)) {
@@ -6814,7 +6915,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
                        struct imsm_disk *disk;
 
                        /* reset the potential in-sync count on even-numbered
-                        * slots.  num_copies is always 2 for imsm raid10 
+                        * slots.  num_copies is always 2 for imsm raid10
                         */
                        if ((i & 1) == 0)
                                insync = 2;
@@ -6907,8 +7008,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) {
-               fprintf(stderr, "%s: subarry index %d, out of range\n",
-                       __func__, atoi(inst));
+               pr_err("subarry index %d, out of range\n", atoi(inst));
                return -ENODEV;
        }
 
@@ -7005,6 +7105,12 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
        if (!super->missing)
                return;
 
+       /* When orom adds replacement for missing disk it does
+        * not remove entry of missing disk, but just updates map with
+        * new added disk. So it is not enough just to test if there is
+        * any missing disk, we have to look if there are any failed disks
+        * in map to stop migration */
+
        dprintf("imsm: mark missing\n");
        /* end process for initialization and rebuild only
         */
@@ -7015,7 +7121,8 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
                failed = imsm_count_failed(super, dev, MAP_0);
                map_state = imsm_check_degraded(super, dev, failed, MAP_0);
 
-               end_migration(dev, super, map_state);
+               if (failed)
+                       end_migration(dev, super, map_state);
        }
        for (dl = super->missing; dl; dl = dl->next)
                mark_missing(dev, &dl->disk, dl->index);
@@ -7280,7 +7387,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
        __u8 map_state;
 
        if (n > map->num_members)
-               fprintf(stderr, "imsm: set_disk %d out of range 0..%d\n",
+               pr_err("imsm: set_disk %d out of range 0..%d\n",
                        n, map->num_members - 1);
 
        if (n < 0)
@@ -7314,7 +7421,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) {
@@ -7322,8 +7429,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++;
@@ -7338,7 +7445,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
@@ -7350,26 +7457,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 {
@@ -7380,22 +7487,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;
@@ -7403,10 +7510,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)
@@ -7468,7 +7574,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;
 }
@@ -7584,7 +7690,6 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot,
        return dl;
 }
 
-
 static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
 {
        struct imsm_dev *dev2;
@@ -7670,8 +7775,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
        /* Cannot activate another spare if rebuild is in progress already
         */
        if (is_rebuilding(dev)) {
-               dprintf("imsm: No spare activation allowed. "
-                       "Rebuild in progress already.\n");
+               dprintf("imsm: No spare activation allowed. Rebuild in progress already.\n");
                return NULL;
        }
 
@@ -7685,14 +7789,18 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
                        IMSM_T_STATE_DEGRADED)
                return NULL;
 
+       if (get_imsm_map(dev, MAP_0)->map_state == IMSM_T_STATE_UNINITIALIZED) {
+               dprintf("imsm: No spare activation allowed. Volume is not initialized.\n");
+               return NULL;
+       }
+
        /*
         * If there are any failed disks check state of the other volume.
         * Block rebuild if the another one is failed until failed disks
         * are removed from container.
         */
        if (failed) {
-               dprintf("found failed disks in %.*s, check if there another"
-                       "failed sub-array.\n",
+               dprintf("found failed disks in %.*s, check if there anotherfailed sub-array.\n",
                        MAX_RAID_SERIAL_LEN, dev->volume);
                /* check if states of the other volumes allow for rebuild */
                for (i = 0; i <  super->anchor->num_raid_devs; i++) {
@@ -7728,12 +7836,9 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
                        dl = imsm_add_spare(super, i, a, 1, rv);
                if (!dl)
                        continue;
+
                /* found a usable disk with enough space */
-               di = malloc(sizeof(*di));
-               if (!di)
-                       continue;
-               memset(di, 0, sizeof(*di));
+               di = xcalloc(1, sizeof(*di));
 
                /* dl->index will be -1 in the case we are activating a
                 * pristine spare.  imsm_process_update() will create a
@@ -7771,24 +7876,9 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
         * Create a metadata_update record to update the
         * disk_ord_tbl for the array
         */
-       mu = malloc(sizeof(*mu));
-       if (mu) {
-               mu->buf = malloc(sizeof(struct imsm_update_activate_spare) * num_spares);
-               if (mu->buf == NULL) {
-                       free(mu);
-                       mu = NULL;
-               }
-       }
-       if (!mu) {
-               while (rv) {
-                       struct mdinfo *n = rv->next;
-
-                       free(rv);
-                       rv = n;
-               }
-               return NULL;
-       }
-
+       mu = xmalloc(sizeof(*mu));
+       mu->buf = xcalloc(num_spares,
+                         sizeof(struct imsm_update_activate_spare));
        mu->space = NULL;
        mu->space_list = NULL;
        mu->len = sizeof(struct imsm_update_activate_spare) * num_spares;
@@ -7830,10 +7920,10 @@ static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_
        return 0;
 }
 
-
 static struct dl *get_disk_super(struct intel_super *super, int major, int minor)
 {
-       struct dl *dl = NULL;
+       struct dl *dl;
+
        for (dl = super->disks; dl; dl = dl->next)
                if ((dl->major == major) &&  (dl->minor == minor))
                        return dl;
@@ -7842,7 +7932,7 @@ static struct dl *get_disk_super(struct intel_super *super, int major, int minor
 
 static int remove_disk_super(struct intel_super *super, int major, int minor)
 {
-       struct dl *prev = NULL;
+       struct dl *prev;
        struct dl *dl;
 
        prev = NULL;
@@ -7855,8 +7945,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;
@@ -7869,7 +7958,8 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
 static int add_remove_disk_update(struct intel_super *super)
 {
        int check_degraded = 0;
-       struct dl *disk = NULL;
+       struct dl *disk;
+
        /* add/remove some spares to/from the metadata/contrainer */
        while (super->disk_mgmt_list) {
                struct dl *disk_cfg;
@@ -7882,9 +7972,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);
@@ -7908,7 +7997,6 @@ static int add_remove_disk_update(struct intel_super *super)
        return check_degraded;
 }
 
-
 static int apply_reshape_migration_update(struct imsm_update_reshape_migration *u,
                                                struct intel_super *super,
                                                void ***space_list)
@@ -7917,7 +8005,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);
@@ -7995,8 +8083,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
                                new_disk = get_disk_super(super,
                                                        major(u->new_disks[0]),
                                                        minor(u->new_disks[0]));
-                               dprintf("imsm: new disk for reshape is: %i:%i "
-                                       "(%p, index = %i)\n",
+                               dprintf("imsm: new disk for reshape is: %i:%i (%p, index = %i)\n",
                                        major(u->new_disks[0]),
                                        minor(u->new_disks[0]),
                                        new_disk, new_disk->index);
@@ -8037,7 +8124,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);
@@ -8054,8 +8141,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);
@@ -8068,7 +8154,6 @@ static int apply_size_change_update(struct imsm_update_size_change *u,
        return ret_val;
 }
 
-
 static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
                                       struct intel_super *super,
                                       struct active_array *active_array)
@@ -8098,8 +8183,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
                                break;
 
                if (!dl) {
-                       fprintf(stderr, "error: imsm_activate_spare passed "
-                               "an unknown disk (index: %d)\n",
+                       pr_err("error: imsm_activate_spare passed an unknown disk (index: %d)\n",
                                u->dl->index);
                        return 0;
                }
@@ -8199,15 +8283,14 @@ 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++) {
                new_disk = get_disk_super(super,
                                          major(u->new_disks[i]),
                                          minor(u->new_disks[i]));
-               dprintf("imsm: new disk for reshape is: %i:%i "
-                       "(%p, index = %i)\n",
+               dprintf("imsm: new disk for reshape is: %i:%i (%p, index = %i)\n",
                        major(u->new_disks[i]), minor(u->new_disks[i]),
                        new_disk, new_disk->index);
                if ((new_disk == NULL) ||
@@ -8404,9 +8487,9 @@ static void imsm_process_update(struct supertype *st,
         *      the arrays for general migration and convert selected spares
         *      into active devices.
         *    update_activate_spare - a spare device has replaced a failed
-        *      device in an array, update the disk_ord_tbl.  If this disk is
-        *      present in all member arrays then also clear the SPARE_DISK
-        *      flag
+        *      device in an array, update the disk_ord_tbl.  If this disk is
+        *      present in all member arrays then also clear the SPARE_DISK
+        *      flag
         *    update_create_array
         *    update_kill_array
         *    update_rename_array
@@ -8440,8 +8523,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) {
@@ -8483,7 +8565,7 @@ static void imsm_process_update(struct supertype *st,
                break;
        }
        case update_activate_spare: {
-               struct imsm_update_activate_spare *u = (void *) update->buf; 
+               struct imsm_update_activate_spare *u = (void *) update->buf;
                if (apply_update_activate_spare(u, super, st->arrays))
                        super->updates_pending++;
                break;
@@ -8510,15 +8592,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;
                }
 
@@ -8543,14 +8624,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;
                }
 
@@ -8562,7 +8643,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;
                        }
                }
@@ -8668,7 +8749,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)) {
@@ -8681,15 +8762,14 @@ static void imsm_process_update(struct supertype *st,
                break;
        }
        default:
-               fprintf(stderr, "error: unsuported process update type:"
-                       "(type: %d)\n", type);
+               pr_err("error: unsuported process update type:(type: %d)\n",    type);
        }
 }
 
 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
@@ -8698,19 +8778,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);
@@ -8718,15 +8806,10 @@ static void imsm_prepare_update(struct supertype *st,
                        int num_members = map->num_members;
                        void *space;
                        int size, i;
-                       int err = 0;
                        /* allocate memory for added disks */
                        for (i = 0; i < num_members; i++) {
                                size = sizeof(struct dl);
-                               space = malloc(size);
-                               if (!space) {
-                                       err++;
-                                       break;
-                               }
+                               space = xmalloc(size);
                                *tail = space;
                                tail = space;
                                *tail = NULL;
@@ -8734,24 +8817,11 @@ static void imsm_prepare_update(struct supertype *st,
                        /* allocate memory for new device */
                        size = sizeof_imsm_dev(super->devlist->dev, 0) +
                                (num_members * sizeof(__u32));
-                       space = malloc(size);
-                       if (!space)
-                               err++;
-                       else {
-                               *tail = space;
-                               tail = space;
-                               *tail = NULL;
-                       }
-                       if (!err) {
-                               len = disks_to_mpb_size(num_members * 2);
-                       } else {
-                               /* if allocation didn't success, free buffer */
-                               while (update->space_list) {
-                                       void **sp = update->space_list;
-                                       update->space_list = *sp;
-                                       free(sp);
-                               }
-                       }
+                       space = xmalloc(size);
+                       *tail = space;
+                       tail = space;
+                       *tail = NULL;
+                       len = disks_to_mpb_size(num_members * 2);
                }
 
                break;
@@ -8769,7 +8839,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);
@@ -8777,9 +8850,7 @@ static void imsm_prepare_update(struct supertype *st,
                        if (u->new_raid_disks > u->old_raid_disks)
                                size += sizeof(__u32)*2*
                                        (u->new_raid_disks - u->old_raid_disks);
-                       s = malloc(size);
-                       if (!s)
-                               break;
+                       s = xmalloc(size);
                        *space_tail = s;
                        space_tail = s;
                        *space_tail = NULL;
@@ -8803,7 +8874,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
                 */
@@ -8813,9 +8887,7 @@ static void imsm_prepare_update(struct supertype *st,
                                if (u->new_raid_disks > u->old_raid_disks)
                                        size += sizeof(__u32)*2*
                                        (u->new_raid_disks - u->old_raid_disks);
-                               s = malloc(size);
-                               if (!s)
-                                       break;
+                               s = xmalloc(size);
                                *space_tail = s;
                                space_tail = s;
                                *space_tail = NULL;
@@ -8828,12 +8900,7 @@ static void imsm_prepare_update(struct supertype *st,
                /* add space for disk in update
                 */
                size = sizeof(struct dl);
-               s = malloc(size);
-               if (!s) {
-                       free(update->space_list);
-                       update->space_list = NULL;
-                       break;
-               }
+               s = xmalloc(size);
                *space_tail = s;
                space_tail = s;
                *space_tail = NULL;
@@ -8877,6 +8944,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: {
@@ -8889,19 +8963,15 @@ 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 */
-               dv = malloc(sizeof(*dv));
-               if (dv) {
-                       dv->dev = malloc(len);
-                       if (dv->dev)
-                               update->space = dv;
-                       else {
-                               free(dv);
-                               update->space = NULL;
-                       }
-               }
+               dv = xmalloc(sizeof(*dv));
+               dv->dev = xmalloc(len);
+               update->space = dv;
 
                /* count how many spares will be converted to members */
                for (i = 0; i < map->num_members; i++) {
@@ -8917,9 +8987,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 */
@@ -8943,6 +9026,7 @@ static void imsm_prepare_update(struct supertype *st,
                else
                        super->next_buf = NULL;
        }
+       return 1;
 }
 
 /* must be called while manager is quiesced */
@@ -8955,8 +9039,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)
@@ -9066,7 +9149,6 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
        }
 }
 
-
 /*******************************************************************************
  * Function:   open_backup_targets
  * Description:        Function opens file descriptors for all devices given in
@@ -9107,7 +9189,7 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
                             sd->disk.minor, 1);
                raid_fds[sd->disk.raid_disk] = dev_open(dn, O_RDWR);
                if (raid_fds[sd->disk.raid_disk] < 0) {
-                       fprintf(stderr, "cannot open component\n");
+                       pr_err("cannot open component\n");
                        continue;
                }
                opened++;
@@ -9118,13 +9200,90 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
                        imsm_get_allowed_degradation(info->new_level,
                                                     raid_disks,
                                                     super, dev)) {
-               fprintf(stderr, "Not enough disks can be opened.\n");
+               pr_err("Not enough disks can be opened.\n");
                close_targets(raid_fds, raid_disks);
                return -2;
        }
        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) || ((hba->type == SYS_DEV_VMD) && (hba != hba2))) {
+                       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
@@ -9178,7 +9337,6 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
        migr_rec->post_migr_vol_cap =  dev->size_low;
        migr_rec->post_migr_vol_cap_hi = dev->size_high;
 
-
        /* Find the smallest dev */
        for (sd = info->devs ; sd ; sd = sd->next) {
                sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
@@ -9223,8 +9381,8 @@ int save_backup_imsm(struct supertype *st,
 {
        int rv = -1;
        struct intel_super *super = st->sb;
-       unsigned long long *target_offsets = NULL;
-       int *targets = NULL;
+       unsigned long long *target_offsets;
+       int *targets;
        int i;
        struct imsm_map *map_dest = get_imsm_map(dev, MAP_0);
        int new_disks = map_dest->num_members;
@@ -9233,16 +9391,12 @@ int save_backup_imsm(struct supertype *st,
        unsigned long long start;
        int data_disks = imsm_num_data_members(dev, MAP_0);
 
-       targets = malloc(new_disks * sizeof(int));
-       if (!targets)
-               goto abort;
+       targets = xmalloc(new_disks * sizeof(int));
 
        for (i = 0; i < new_disks; i++)
                targets[i] = -1;
 
-       target_offsets = malloc(new_disks * sizeof(unsigned long long));
-       if (!target_offsets)
-               goto abort;
+       target_offsets = xcalloc(new_disks, sizeof(unsigned long long));
 
        start = info->reshape_progress * 512;
        for (i = 0; i < new_disks; i++) {
@@ -9273,7 +9427,7 @@ int save_backup_imsm(struct supertype *st,
                            start,
                            length,
                            buf) != 0) {
-               fprintf(stderr, Name ": Error restoring stripes\n");
+               pr_err("Error restoring stripes\n");
                goto abort;
        }
 
@@ -9309,8 +9463,7 @@ int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
        unsigned long long curr_migr_unit;
 
        if (load_imsm_migr_rec(super, info) != 0) {
-               dprintf("imsm: ERROR: Cannot read migration record "
-                       "for checkpoint save.\n");
+               dprintf("imsm: ERROR: Cannot read migration record for checkpoint save.\n");
                return 1;
        }
 
@@ -9334,8 +9487,7 @@ int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
                __cpu_to_le32(curr_migr_unit *
                              __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
        if (write_imsm_migr_rec(st) < 0) {
-               dprintf("imsm: Cannot write migration record "
-                       "outside backup area\n");
+               dprintf("imsm: Cannot write migration record outside backup area\n");
                return 1;
        }
 
@@ -9357,7 +9509,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
 {
        struct intel_super *super = st->sb;
        struct migr_record *migr_rec = super->migr_rec;
-       struct imsm_map *map_dest = NULL;
+       struct imsm_map *map_dest;
        struct intel_dev *id = NULL;
        unsigned long long read_offset;
        unsigned long long write_offset;
@@ -9404,13 +9556,10 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
        unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512;
        if (posix_memalign((void **)&buf, 512, unit_len) != 0)
                goto abort;
-       targets = malloc(new_disks * sizeof(int));
-       if (!targets)
-               goto abort;
+       targets = xcalloc(new_disks, sizeof(int));
 
        if (open_backup_targets(info, new_disks, targets, super, id->dev)) {
-               fprintf(stderr,
-                       Name ": Cannot open some devices belonging to array.\n");
+               pr_err("Cannot open some devices belonging to array.\n");
                goto abort;
        }
 
@@ -9420,30 +9569,26 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
                        continue;
                }
                if (lseek64(targets[i], read_offset, SEEK_SET) < 0) {
-                       fprintf(stderr,
-                               Name ": Cannot seek to block: %s\n",
-                               strerror(errno));
+                       pr_err("Cannot seek to block: %s\n",
+                              strerror(errno));
                        skipped_disks++;
                        continue;
                }
                if ((unsigned)read(targets[i], buf, unit_len) != unit_len) {
-                       fprintf(stderr,
-                               Name ": Cannot read copy area block: %s\n",
-                               strerror(errno));
+                       pr_err("Cannot read copy area block: %s\n",
+                              strerror(errno));
                        skipped_disks++;
                        continue;
                }
                if (lseek64(targets[i], write_offset, SEEK_SET) < 0) {
-                       fprintf(stderr,
-                               Name ": Cannot seek to block: %s\n",
-                               strerror(errno));
+                       pr_err("Cannot seek to block: %s\n",
+                              strerror(errno));
                        skipped_disks++;
                        continue;
                }
                if ((unsigned)write(targets[i], buf, unit_len) != unit_len) {
-                       fprintf(stderr,
-                               Name ": Cannot restore block: %s\n",
-                               strerror(errno));
+                       pr_err("Cannot restore block: %s\n",
+                              strerror(errno));
                        skipped_disks++;
                        continue;
                }
@@ -9453,17 +9598,14 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
                                                         new_disks,
                                                         super,
                                                         id->dev)) {
-               fprintf(stderr,
-                       Name ": Cannot restore data from backup."
-                       " Too many failed disks\n");
+               pr_err("Cannot restore data from backup. Too many failed disks\n");
                goto abort;
        }
 
        if (save_checkpoint_imsm(st, info, UNIT_SRC_NORMAL)) {
                /* ignore error == 2, this can mean end of reshape here
                 */
-               dprintf("imsm: Cannot write checkpoint to "
-                       "migration record (UNIT_SRC_NORMAL) during restart\n");
+               dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL) during restart\n");
        } else
                retval = 0;
 
@@ -9486,11 +9628,11 @@ 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;
-               char *path=NULL;
+               char *path;
 
                path = devt_to_devpath(st.st_rdev);
                if (path == NULL)
@@ -9500,30 +9642,29 @@ static const char *imsm_get_disk_controller_domain(const char *path)
                        drv = "isci";
                else if (hba && hba->type == SYS_DEV_SATA)
                        drv = "ahci";
-               else 
+               else
                        drv = "unknown";
                dprintf("path: %s hba: %s attached: %s\n",
                        path, (hba) ? hba->path : "NULL", drv);
                free(path);
-               if (hba)
-                       free_sys_dev(&hba);
        }
        return drv;
 }
 
-static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor)
+static char *imsm_find_array_devnm_by_subdev(int subdev, char *container)
 {
+       static char devnm[32];
        char subdev_name[20];
        struct mdstat_ent *mdstat;
 
        sprintf(subdev_name, "%d", subdev);
        mdstat = mdstat_by_subdev(subdev_name, container);
        if (!mdstat)
-               return -1;
+               return NULL;
 
-       *minor = mdstat->devnum;
+       strcpy(devnm, mdstat->devnm);
        free_mdstat(mdstat);
-       return 0;
+       return devnm;
 }
 
 static int imsm_reshape_is_allowed_on_container(struct supertype *st,
@@ -9539,30 +9680,25 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
        struct mdinfo *info, *member;
        int devices_that_can_grow = 0;
 
-       dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): "
-               "st->devnum = (%i)\n",
-               st->devnum);
+       dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): st->devnm = (%s)\n", st->devnm);
 
-       if (geo->size != -1 ||
+       if (geo->size > 0 ||
            geo->level != UnSet ||
            geo->layout != UnSet ||
            geo->chunksize != 0 ||
            geo->raid_disks == UnSet) {
-               dprintf("imsm: Container operation is allowed for "
-                       "raid disks number change only.\n");
+               dprintf("imsm: Container operation is allowed for raid disks number change only.\n");
                return ret_val;
        }
 
        if (direction == ROLLBACK_METADATA_CHANGES) {
-               dprintf("imsm: Metadata changes rollback is not supported for "
-                       "container operation.\n");
+               dprintf("imsm: Metadata changes rollback is not supported for container operation.\n");
                return ret_val;
        }
 
        info = container_content_imsm(st, NULL);
        for (member = info; member; member = member->next) {
-               int result;
-               int minor;
+               char *result;
 
                dprintf("imsm: checking device_num: %i\n",
                        member->container_member);
@@ -9571,8 +9707,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                        /* we work on container for Online Capacity Expansion
                         * only so raid_disks has to grow
                         */
-                       dprintf("imsm: for container operation raid disks "
-                               "increase is required\n");
+                       dprintf("imsm: for container operation raid disks increase is required\n");
                        break;
                }
 
@@ -9580,8 +9715,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                    (info->array.level != 5)) {
                        /* we cannot use this container with other raid level
                         */
-                       dprintf("imsm: for container operation wrong"
-                               " raid level (%i) detected\n",
+                       dprintf("imsm: for container operation wrong raid level (%i) detected\n",
                                info->array.level);
                        break;
                } else {
@@ -9592,8 +9726,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                        if (!is_raid_level_supported(super->orom,
                                                     member->array.level,
                                                     geo->raid_disks)) {
-                               dprintf("platform does not support raid%d with"
-                                       " %d disk%s\n",
+                               dprintf("platform does not support raid%d with %d disk%s\n",
                                         info->array.level,
                                         geo->raid_disks,
                                         geo->raid_disks > 1 ? "s" : "");
@@ -9603,8 +9736,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                         */
                        if (info->component_size %
                            (info->array.chunk_size/512)) {
-                               dprintf("Component size is not aligned to "
-                                       "chunk size\n");
+                               dprintf("Component size is not aligned to chunk size\n");
                                break;
                        }
                }
@@ -9619,10 +9751,9 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
                 * so they need to be assembled.  We have already
                 * checked that no recovery etc is happening.
                 */
-               result = imsm_find_array_minor_by_subdev(member->container_member,
-                                                        st->container_dev,
-                                                        &minor);
-               if (result < 0) {
+               result = imsm_find_array_devnm_by_subdev(member->container_member,
+                                                        st->container_devnm);
+               if (result == NULL) {
                        dprintf("imsm: cannot find array\n");
                        break;
                }
@@ -9633,19 +9764,19 @@ 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;
 }
 
 /* Function: get_spares_for_grow
  * Description: Allocates memory and creates list of spare devices
- *             avaliable in container. Checks if spare drive size is acceptable.
+ *             avaliable in container. Checks if spare drive size is acceptable.
  * Parameters: Pointer to the supertype structure
  * Returns: Pointer to the list of spare devices (mdinfo structure) on success,
- *             NULL if fail
+ *             NULL if fail
  */
 static struct mdinfo *get_spares_for_grow(struct supertype *st)
 {
@@ -9666,15 +9797,14 @@ static int imsm_create_metadata_update_for_reshape(
 {
        struct intel_super *super = st->sb;
        struct imsm_super *mpb = super->anchor;
-       int update_memory_size = 0;
-       struct imsm_update_reshape *u = NULL;
-       struct mdinfo *spares = NULL;
+       int update_memory_size;
+       struct imsm_update_reshape *u;
+       struct mdinfo *spares;
        int i;
-       int delta_disks = 0;
+       int delta_disks;
        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;
 
@@ -9684,12 +9814,7 @@ static int imsm_create_metadata_update_for_reshape(
        /* now add space for spare disks that we need to add. */
        update_memory_size += sizeof(u->new_disks[0]) * (delta_disks - 1);
 
-       u = calloc(1, update_memory_size);
-       if (u == NULL) {
-               dprintf("error: "
-                       "cannot get memory for imsm_update_reshape update\n");
-               return 0;
-       }
+       u = xcalloc(1, update_memory_size);
        u->type = update_reshape_container_disks;
        u->old_raid_disks = old_raid_disks;
        u->new_raid_disks = geo->raid_disks;
@@ -9700,8 +9825,7 @@ static int imsm_create_metadata_update_for_reshape(
 
        if (spares == NULL
            || delta_disks > spares->array.spare_disks) {
-               fprintf(stderr, Name ": imsm: ERROR: Cannot get spare devices "
-                       "for %s.\n", geo->dev_name);
+               pr_err("imsm: ERROR: Cannot get spare devices for %s.\n", geo->dev_name);
                i = -1;
                goto abort;
        }
@@ -9733,17 +9857,16 @@ 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;
 }
 
-
 /******************************************************************************
  * function: imsm_create_metadata_update_for_size_change()
  *           Creates update for IMSM array for array size change.
@@ -9755,21 +9878,15 @@ static int imsm_create_metadata_update_for_size_change(
                                struct imsm_update_size_change **updatep)
 {
        struct intel_super *super = st->sb;
-       int update_memory_size = 0;
-       struct imsm_update_size_change *u = NULL;
+       int update_memory_size;
+       struct imsm_update_size_change *u;
 
-       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);
 
-       u = calloc(1, update_memory_size);
-       if (u == NULL) {
-               dprintf("error: cannot get memory for "
-                       "imsm_create_metadata_update_for_size_change\n");
-               return 0;
-       }
+       u = xcalloc(1, update_memory_size);
        u->type = update_size_change;
        u->subdev = super->current_vol;
        u->new_size = geo->size;
@@ -9791,23 +9908,17 @@ static int imsm_create_metadata_update_for_migration(
                                        struct imsm_update_reshape_migration **updatep)
 {
        struct intel_super *super = st->sb;
-       int update_memory_size = 0;
-       struct imsm_update_reshape_migration *u = NULL;
+       int update_memory_size;
+       struct imsm_update_reshape_migration *u;
        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);
 
-       u = calloc(1, update_memory_size);
-       if (u == NULL) {
-               dprintf("error: cannot get memory for "
-                       "imsm_create_metadata_update_for_migration\n");
-               return 0;
-       }
+       u = xcalloc(1, update_memory_size);
        u->type = update_reshape_migration;
        u->subdev = super->current_vol;
        u->new_level = geo->level;
@@ -9827,8 +9938,7 @@ static int imsm_create_metadata_update_for_migration(
 
                        if (geo->chunksize != current_chunk_size) {
                                u->new_chunksize = geo->chunksize / 1024;
-                               dprintf("imsm: "
-                                       "chunk size change from %i to %i\n",
+                               dprintf("imsm: chunk size change from %i to %i\n",
                                        current_chunk_size, u->new_chunksize);
                        }
                        previous_level = map->raid_level;
@@ -9843,8 +9953,7 @@ static int imsm_create_metadata_update_for_migration(
                        free(u);
                        sysfs_free(spares);
                        update_memory_size = 0;
-                       dprintf("error: cannot get spare device "
-                               "for requested migration");
+                       dprintf("error: cannot get spare device for requested migration");
                        return 0;
                }
                sysfs_free(spares);
@@ -9865,8 +9974,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;
@@ -9878,7 +9987,7 @@ static void imsm_update_metadata_locally(struct supertype *st,
 /***************************************************************************
 * Function:    imsm_analyze_change
 * Description: Function analyze change for single volume
-*              and validate if transition is supported
+*              and validate if transition is supported
 * Parameters:  Geometry parameters, supertype structure,
 *              metadata change direction (apply/rollback)
 * Returns:     Operation type code on success, -1 if fail
@@ -9898,7 +10007,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
        int data_disks;
        struct imsm_dev *dev;
        struct intel_super *super;
-       long long current_size;
+       unsigned long long current_size;
+       unsigned long long free_size;
+       unsigned long long max_size;
+       int rv;
 
        getinfo_super_imsm_volume(st, &info, NULL);
        if ((geo->level != info.array.level) &&
@@ -9909,10 +10021,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        if (geo->level == 5) {
                                change = CH_MIGRATION;
                                if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) {
-                                       fprintf(stderr,
-                                       Name " Error. Requested Layout "
-                                       "not supported (left-asymmetric layout "
-                                       "is supported only)!\n");
+                                       pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n");
                                        change = -1;
                                        goto analyse_change_exit;
                                }
@@ -9937,10 +10046,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        break;
                }
                if (change == -1) {
-                       fprintf(stderr,
-                               Name " Error. Level Migration from %d to %d "
-                               "not supported!\n",
-                               info.array.level, geo->level);
+                       pr_err("Error. Level Migration from %d to %d not supported!\n",
+                              info.array.level, geo->level);
                        goto analyse_change_exit;
                }
        } else
@@ -9960,10 +10067,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        geo->layout = 0;
                        geo->level = 5;
                } else {
-                       fprintf(stderr,
-                               Name " Error. Layout Migration from %d to %d "
-                               "not supported!\n",
-                               info.array.layout, geo->layout);
+                       pr_err("Error. Layout Migration from %d to %d not supported!\n",
+                              info.array.layout, geo->layout);
                        change = -1;
                        goto analyse_change_exit;
                }
@@ -9988,52 +10093,57 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
         */
        current_size = info.custom_array_size / data_disks;
 
-       if (geo->size > 0) {
+       if ((geo->size > 0) && (geo->size != MAX_SIZE)) {
                /* align component size
                 */
                geo->size = imsm_component_size_aligment_check(
                                    get_imsm_raid_level(dev->vol.map),
                                    chunk * 1024,
                                    geo->size * 2);
+               if (geo->size == 0) {
+                       pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is 0).\n",
+                                  current_size);
+                       goto analyse_change_exit;
+               }
        }
 
-       if ((current_size != geo->size) && (geo->size >= 0)) {
+       if ((current_size != geo->size) && (geo->size > 0)) {
                if (change != -1) {
-                       fprintf(stderr,
-                               Name " Error. Size change should be the only "
-                               "one at a time.\n");
+                       pr_err("Error. Size change should be the only one at a time.\n");
                        change = -1;
                        goto analyse_change_exit;
                }
                if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
-                       fprintf(stderr,
-                               Name " Error. The last volume in container "
-                               "can be expanded only (%i/%i).\n",
-                               super->current_vol, st->devnum);
+                       pr_err("Error. The last volume in container can be expanded only (%i/%s).\n",
+                              super->current_vol, st->devnm);
                        goto analyse_change_exit;
                }
-               if (geo->size == 0) {
+               /* check the maximum available size
+                */
+               rv =  imsm_get_free_size(st, dev->vol.map->num_members,
+                                        0, chunk, &free_size);
+               if (rv == 0)
+                       /* Cannot find maximum available space
+                        */
+                       max_size = 0;
+               else {
+                       max_size = free_size + current_size;
+                       /* align component size
+                        */
+                       max_size = imsm_component_size_aligment_check(
+                                       get_imsm_raid_level(dev->vol.map),
+                                       chunk * 1024,
+                                       max_size);
+               }
+               if (geo->size == MAX_SIZE) {
                        /* requested size change to the maximum available size
                         */
-                       unsigned long long freesize;
-                       int rv;
-
-                       rv =  imsm_get_free_size(st, dev->vol.map->num_members,
-                                                0, chunk, &freesize);
-                       if (rv == 0) {
-                               fprintf(stderr, Name " Error. Cannot find "
-                                       "maximum available space.\n");
+                       if (max_size == 0) {
+                               pr_err("Error. Cannot find maximum available space.\n");
                                change = -1;
                                goto analyse_change_exit;
-                       }
-                       geo->size = freesize + current_size;
-
-                       /* align component size
-                        */
-                       geo->size = imsm_component_size_aligment_check(
-                                             get_imsm_raid_level(dev->vol.map),
-                                             chunk * 1024,
-                                             geo->size);
+                       } else
+                               geo->size = max_size;
                }
 
                if ((direction == ROLLBACK_METADATA_CHANGES)) {
@@ -10047,11 +10157,13 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        dprintf("Prepare update for size change to %llu\n",
                                geo->size );
                        if (current_size >= geo->size) {
-                               fprintf(stderr,
-                                       Name " Error. Size expanssion is "
-                                       "supported only (current size is %llu, "
-                                       "requested size /rounded/ is %llu).\n",
-                                       current_size, geo->size);
+                               pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is %llu).\n",
+                                      current_size, geo->size);
+                               goto analyse_change_exit;
+                       }
+                       if (max_size && geo->size > max_size) {
+                               pr_err("Error. Requested size is larger than maximum available size (maximum available size is %llu, requested size /rounded/ is %llu).\n",
+                                      max_size, geo->size);
                                goto analyse_change_exit;
                        }
                }
@@ -10064,7 +10176,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                                    imsm_layout,
                                    geo->raid_disks + devNumChange,
                                    &chunk,
-                                   geo->size,
+                                   geo->size, INVALID_SECTORS,
                                    0, 0, 1))
                change = -1;
 
@@ -10073,11 +10185,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                struct imsm_super *mpb = super->anchor;
 
                if (mpb->num_raid_devs > 1) {
-                       fprintf(stderr,
-                               Name " Error. Cannot perform operation on %s"
-                               "- for this operation it MUST be single "
-                               "array in container\n",
-                               geo->dev_name);
+                       pr_err("Error. Cannot perform operation on %s- for this operation it MUST be single array in container\n",
+                              geo->dev_name);
                        change = -1;
                }
        }
@@ -10085,8 +10194,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
 analyse_change_exit:
        if ((direction == ROLLBACK_METADATA_CHANGES) &&
             ((change == CH_MIGRATION) || (change == CH_TAKEOVER))) {
-               dprintf("imsm: Metadata changes rollback is not supported for "
-                       "migration and takeover operations.\n");
+               dprintf("imsm: Metadata changes rollback is not supported for migration and takeover operations.\n");
                change = -1;
        }
        return change;
@@ -10097,9 +10205,7 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
        struct intel_super *super = st->sb;
        struct imsm_update_takeover *u;
 
-       u = malloc(sizeof(struct imsm_update_takeover));
-       if (u == NULL)
-               return 1;
+       u = xmalloc(sizeof(struct imsm_update_takeover));
 
        u->type = update_takeover;
        u->subarray = super->current_vol;
@@ -10125,7 +10231,8 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
        return 0;
 }
 
-static int imsm_reshape_super(struct supertype *st, long long size, int level,
+static int imsm_reshape_super(struct supertype *st, unsigned long long size,
+                             int level,
                              int layout, int chunksize, int raid_disks,
                              int delta_disks, char *backup, char *dev,
                              int direction, int verbose)
@@ -10133,12 +10240,12 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
        int ret_val = 1;
        struct geo_params geo;
 
-       dprintf("imsm: reshape_super called.\n");
+       dprintf("(enter)\n");
 
        memset(&geo, 0, sizeof(struct geo_params));
 
        geo.dev_name = dev;
-       geo.dev_id = st->devnum;
+       strcpy(geo.devnm, st->devnm);
        geo.size = size;
        geo.level = level;
        geo.layout = layout;
@@ -10147,13 +10254,13 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
        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;
 
-       if (st->container_dev == st->devnum) {
+       if (strcmp(st->container_devnm, st->devnm) == 0) {
                /* On container level we can only increase number of devices. */
                dprintf("imsm: info: Container operation\n");
                int old_raid_disks = 0;
@@ -10181,8 +10288,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                                free(u);
 
                } else {
-                       fprintf(stderr, Name ": (imsm) Operation "
-                               "is not allowed on this container\n");
+                       pr_err("(imsm) Operation is not allowed on this container\n");
                }
        } else {
                /* On volume level we support following operations
@@ -10192,19 +10298,20 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                 */
                struct intel_super *super = st->sb;
                struct intel_dev *dev = super->devlist;
-               int change, devnum;
+               int change;
                dprintf("imsm: info: Volume operation\n");
                /* find requested device */
                while (dev) {
-                       if (imsm_find_array_minor_by_subdev(
-                                   dev->index, st->container_dev, &devnum) == 0
-                           && devnum == geo.dev_id)
+                       char *devnm =
+                               imsm_find_array_devnm_by_subdev(
+                                       dev->index, st->container_devnm);
+                       if (devnm && strcmp(devnm, geo.devnm) == 0)
                                break;
                        dev = dev->next;
                }
                if (dev == NULL) {
-                       fprintf(stderr, Name " Cannot find %s (%i) subarray\n",
-                               geo.dev_name, geo.dev_id);
+                       pr_err("Cannot find %s (%s) subarray\n",
+                               geo.dev_name, geo.devnm);
                        goto exit_imsm_reshape_super;
                }
                super->current_vol = dev->index;
@@ -10219,8 +10326,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                                imsm_create_metadata_update_for_migration(
                                        st, &geo, &u);
                        if (len < 1) {
-                               dprintf("imsm: "
-                                       "Cannot prepare update\n");
+                               dprintf("imsm: Cannot prepare update\n");
                                break;
                        }
                        ret_val = 0;
@@ -10239,8 +10345,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                                imsm_create_metadata_update_for_size_change(
                                        st, &geo, &u);
                        if (len < 1) {
-                               dprintf("imsm: "
-                                       "Cannot prepare update\n");
+                               dprintf("imsm: Cannot prepare update\n");
                                break;
                        }
                        ret_val = 0;
@@ -10263,6 +10368,33 @@ exit_imsm_reshape_super:
        return ret_val;
 }
 
+#define COMPLETED_OK           0
+#define COMPLETED_NONE         1
+#define COMPLETED_DELAYED      2
+
+static int read_completed(int fd, unsigned long long *val)
+{
+       int ret;
+       char buf[50];
+
+       ret = sysfs_fd_get_str(fd, buf, 50);
+       if (ret < 0)
+               return ret;
+
+       ret = COMPLETED_OK;
+       if (strncmp(buf, "none", 4) == 0) {
+               ret = COMPLETED_NONE;
+       } else if (strncmp(buf, "delayed", 7) == 0) {
+               ret = COMPLETED_DELAYED;
+       } else {
+               char *ep;
+               *val = strtoull(buf, &ep, 0);
+               if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' '))
+                       ret = -1;
+       }
+       return ret;
+}
+
 /*******************************************************************************
  * Function:   wait_for_reshape_imsm
  * Description:        Function writes new sync_max value and waits until
@@ -10277,62 +10409,71 @@ exit_imsm_reshape_super:
  ******************************************************************************/
 int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
 {
-       int fd = sysfs_get_fd(sra, NULL, "reshape_position");
+       int fd = sysfs_get_fd(sra, NULL, "sync_completed");
+       int retry = 3;
        unsigned long long completed;
        /* to_complete : new sync_max position */
        unsigned long long to_complete = sra->reshape_progress;
        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");
-               close(fd);
-               return 0;
-       }
+       do {
+               if (sysfs_fd_get_ll(fd, &completed) < 0) {
+                       if (!retry) {
+                               dprintf("cannot read reshape_position (no reshape in progres)\n");
+                               close(fd);
+                               return 1;
+                       }
+                       usleep(30000);
+               } else
+                       break;
+       } while (retry--);
 
-       if (completed > to_complete) {
-               dprintf("imsm: wait_for_reshape_imsm() "
-                       "wrong next position to set %llu (%llu)\n",
-                       to_complete, completed);
+       if (completed > position_to_set) {
+               dprintf("wrong next position to set %llu (%llu)\n",
+                       to_complete, position_to_set);
                close(fd);
                return -1;
        }
        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;
        }
 
        do {
+               int rc;
                char action[20];
-               fd_set rfds;
-               FD_ZERO(&rfds);
-               FD_SET(fd, &rfds);
-               select(fd+1, &rfds, NULL, NULL, NULL);
+               int timeout = 3000;
+
+               sysfs_wait(fd, &timeout);
                if (sysfs_get_str(sra, NULL, "sync_action",
                                  action, 20) > 0 &&
-                               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");
+                               strncmp(action, "reshape", 7) != 0) {
+                       if (strncmp(action, "idle", 4) == 0)
+                               break;
                        close(fd);
-                       return 1;
+                       return -1;
                }
-       } while (completed < to_complete);
+
+               rc = read_completed(fd, &completed);
+               if (rc < 0) {
+                       dprintf("cannot read reshape_position (in loop)\n");
+                       close(fd);
+                       return 1;
+               } else if (rc == COMPLETED_NONE)
+                       break;
+       } while (completed < position_to_set);
+
        close(fd);
        return 0;
-
 }
 
 /*******************************************************************************
@@ -10350,8 +10491,10 @@ int check_degradation_change(struct mdinfo *info,
                             int degraded)
 {
        unsigned long long new_degraded;
-       sysfs_get_ll(info, NULL, "degraded", &new_degraded);
-       if (new_degraded != (unsigned long long)degraded) {
+       int rv;
+
+       rv = sysfs_get_ll(info, NULL, "degraded", &new_degraded);
+       if ((rv == -1) || (new_degraded != (unsigned long long)degraded)) {
                /* check each device to ensure it is still working */
                struct mdinfo *sd;
                new_degraded = 0;
@@ -10386,7 +10529,7 @@ int check_degradation_change(struct mdinfo *info,
  * Function:   imsm_manage_reshape
  * Description:        Function finds array under reshape and it manages reshape
  *             process. It creates stripes backups (if required) and sets
- *             checheckpoits.
+ *             checkpoints.
  * Parameters:
  *     afd             : Backup handle (nattive) - not used
  *     sra             : general array info
@@ -10410,7 +10553,7 @@ static int imsm_manage_reshape(
 {
        int ret_val = 0;
        struct intel_super *super = st->sb;
-       struct intel_dev *dv = NULL;
+       struct intel_dev *dv;
        struct imsm_dev *dev = NULL;
        struct imsm_map *map_src;
        int migr_vol_qan = 0;
@@ -10428,7 +10571,10 @@ static int imsm_manage_reshape(
        int degraded = 0;
        int source_layout = 0;
 
-       if (!fds || !offsets || !sra)
+       if (!sra)
+               return ret_val;
+
+       if (!fds || !offsets)
                goto abort;
 
        /* Find volume during the reshape */
@@ -10441,7 +10587,7 @@ static int imsm_manage_reshape(
        }
        /* Only one volume can migrate at the same time */
        if (migr_vol_qan != 1) {
-               fprintf(stderr, Name " : %s", migr_vol_qan ?
+               pr_err("%s", migr_vol_qan ?
                        "Number of migrating volumes greater than 1\n" :
                        "There is no volume during migrationg\n");
                goto abort;
@@ -10464,8 +10610,7 @@ static int imsm_manage_reshape(
                init_migr_record_imsm(st, dev, sra);
        else {
                if (__le32_to_cpu(migr_rec->rec_status) != UNIT_SRC_NORMAL) {
-                       dprintf("imsm: cannot restart migration when data "
-                               "are present in copy area.\n");
+                       dprintf("imsm: cannot restart migration when data are present in copy area.\n");
                        goto abort;
                }
                /* Save checkpoint to update migration record for current
@@ -10475,9 +10620,7 @@ static int imsm_manage_reshape(
                if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) {
                        /* ignore error == 2, this can mean end of reshape here
                         */
-                       dprintf("imsm: Cannot write checkpoint to "
-                               "migration record (UNIT_SRC_NORMAL, "
-                               "initial save)\n");
+                       dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL, initial save)\n");
                        goto abort;
                }
        }
@@ -10508,8 +10651,7 @@ static int imsm_manage_reshape(
                 */
                degraded = check_degradation_change(sra, fds, degraded);
                if (degraded > 1) {
-                       dprintf("imsm: Abort reshape due to degradation"
-                               " level (%i)\n", degraded);
+                       dprintf("imsm: Abort reshape due to degradation level (%i)\n", degraded);
                        goto abort;
                }
 
@@ -10520,7 +10662,7 @@ static int imsm_manage_reshape(
 
                start = current_position * 512;
 
-               /* allign reading start to old geometry */
+               /* align reading start to old geometry */
                start_buf_shift = start % old_data_stripe_length;
                start_src = start - start_buf_shift;
 
@@ -10534,7 +10676,7 @@ static int imsm_manage_reshape(
                         *             to backup alligned to source array
                         *             [bytes]
                         */
-                       unsigned long long next_step_filler = 0;
+                       unsigned long long next_step_filler;
                        unsigned long long copy_length = next_step * 512;
 
                        /* allign copy area length to stripe in old geometry */
@@ -10543,10 +10685,7 @@ static int imsm_manage_reshape(
                        if (next_step_filler)
                                next_step_filler = (old_data_stripe_length
                                                    - next_step_filler);
-                       dprintf("save_stripes() parameters: start = %llu,"
-                               "\tstart_src = %llu,\tnext_step*512 = %llu,"
-                               "\tstart_in_buf_shift = %llu,"
-                               "\tnext_step_filler = %llu\n",
+                       dprintf("save_stripes() parameters: start = %llu,\tstart_src = %llu,\tnext_step*512 = %llu,\tstart_in_buf_shift = %llu,\tnext_step_filler = %llu\n",
                                start, start_src, copy_length,
                                start_buf_shift, next_step_filler);
 
@@ -10556,8 +10695,7 @@ static int imsm_manage_reshape(
                                         copy_length +
                                         next_step_filler + start_buf_shift,
                                         buf)) {
-                               dprintf("imsm: Cannot save stripes"
-                                       " to buffer\n");
+                               dprintf("imsm: Cannot save stripes to buffer\n");
                                goto abort;
                        }
                        /* Convert data to destination format and store it
@@ -10565,14 +10703,12 @@ static int imsm_manage_reshape(
                         */
                        if (save_backup_imsm(st, dev, sra,
                                buf + start_buf_shift, copy_length)) {
-                               dprintf("imsm: Cannot save stripes to "
-                                       "target devices\n");
+                               dprintf("imsm: Cannot save stripes to target devices\n");
                                goto abort;
                        }
                        if (save_checkpoint_imsm(st, sra,
                                                 UNIT_SRC_IN_CP_AREA)) {
-                               dprintf("imsm: Cannot write checkpoint to "
-                                       "migration record (UNIT_SRC_IN_CP_AREA)\n");
+                               dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_IN_CP_AREA)\n");
                                goto abort;
                        }
                } else {
@@ -10593,29 +10729,52 @@ static int imsm_manage_reshape(
                sra->reshape_progress = next_step;
 
                /* wait until reshape finish */
-               if (wait_for_reshape_imsm(sra, ndata) < 0) {
+               if (wait_for_reshape_imsm(sra, ndata)) {
                        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
                         */
-                       dprintf("imsm: Cannot write checkpoint to "
-                               "migration record (UNIT_SRC_NORMAL)\n");
+                       dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL)\n");
                        goto abort;
                }
 
        }
 
+       /* 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:
        free(buf);
-       abort_reshape(sra);
+       /* See Grow.c: abort_reshape() for further explanation */
+       sysfs_set_num(sra, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL);
+       sysfs_set_num(sra, NULL, "suspend_hi", 0);
+       sysfs_set_num(sra, NULL, "suspend_lo", 0);
 
        return ret_val;
 }
+
 #endif /* MDASSEMBLE */
 
 struct superswitch super_imsm = {
@@ -10631,6 +10790,7 @@ struct superswitch super_imsm = {
        .add_to_super   = add_to_super_imsm,
        .remove_from_super = remove_from_super_imsm,
        .detail_platform = detail_platform_imsm,
+       .export_detail_platform = export_detail_platform_imsm,
        .kill_subarray = kill_subarray_imsm,
        .update_subarray = update_subarray_imsm,
        .load_container = load_container_imsm,
@@ -10639,6 +10799,7 @@ struct superswitch super_imsm = {
        .reshape_super  = imsm_reshape_super,
        .manage_reshape = imsm_manage_reshape,
        .recover_backup = recover_backup_imsm,
+       .copy_metadata = copy_metadata_imsm,
 #endif
        .match_home     = match_home_imsm,
        .uuid_from_super= uuid_from_super_imsm,
@@ -10657,7 +10818,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",