]> 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 66cc8e52d38aea817f534313dc8dc61f03cd6120..cfc8904e2d2cca5df92a54933a3d50ca6ccc5dff 100644 (file)
@@ -510,7 +510,8 @@ static const char *_sys_dev_type[] = {
        [SYS_DEV_UNKNOWN] = "Unknown",
        [SYS_DEV_SAS] = "SAS",
        [SYS_DEV_SATA] = "SATA",
-       [SYS_DEV_NVME] = "NVMe"
+       [SYS_DEV_NVME] = "NVMe",
+       [SYS_DEV_VMD] = "VMD"
 };
 
 const char *get_sys_dev_type(enum sys_dev_type type)
@@ -536,7 +537,8 @@ static struct intel_hba * alloc_intel_hba(struct sys_dev *device)
 
 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;
@@ -565,6 +567,10 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device
        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);
 
@@ -1619,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];
@@ -1649,7 +1658,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
                        break;
                }
                sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor);
-               if (load_sys(device, buf) != 0) {
+               if (load_sys(device, buf, sizeof(buf)) != 0) {
                        if (verbose > 0)
                                pr_err("failed to read device type for %s\n",
                                        path);
@@ -1664,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];
@@ -1673,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];
@@ -1761,6 +1770,61 @@ 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) {
@@ -1771,7 +1835,12 @@ static void print_found_intel_controllers(struct sys_dev *elem)
                        fprintf(stderr, "SAS ");
                else if (elem->type == SYS_DEV_NVME)
                        fprintf(stderr, "NVMe ");
-               fprintf(stderr, "RAID controller");
+
+               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");
@@ -1935,8 +2004,10 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
                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->path, get_sys_dev_type(hba->type));
+                                 hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path,
+                                 get_sys_dev_type(hba->type));
                        continue;
                }
                result = 0;
@@ -1951,13 +2022,31 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
        const struct orom_entry *entry;
 
        for (entry = orom_entries; entry; entry = entry->next) {
-               print_imsm_capability(&entry->orom);
+               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;
+               }
 
-               if (imsm_orom_is_nvme(&entry->orom)) {
+               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;
                }
 
@@ -2000,16 +2089,25 @@ static int export_detail_platform_imsm(int verbose, char *controller_path)
        for (hba = list; hba; hba = hba->next) {
                if (controller_path && (compare_paths(hba->path,controller_path) != 0))
                        continue;
-               if (!find_imsm_capability(hba) && verbose > 0)
-                       pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path);
+               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)
+       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);
+       }
 
        return result;
 }
@@ -2365,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 */
@@ -2491,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);
@@ -2963,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;
@@ -3862,12 +3960,14 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                if (devname) {
                        struct intel_hba *hba = super->hba;
 
-                       pr_err("%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,
                                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(super->hba->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!");
@@ -3876,7 +3976,8 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
                                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");
                }
                return 2;
        }
@@ -4374,7 +4475,7 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list
 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 err = 0;
@@ -4488,7 +4589,11 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
 
        /* retry the load if we might have raced against mdmon */
        if (rv == 3) {
-               struct mdstat_ent *mdstat = mdstat_by_component(fd2devnm(fd));
+               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++) {
@@ -5360,7 +5465,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
 {
        int fd;
        unsigned long long ldsize;
-       struct intel_super *super=NULL;
+       struct intel_super *super;
        int rv = 0;
 
        if (level != LEVEL_CONTAINER)
@@ -5553,10 +5658,10 @@ 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) {
@@ -5573,7 +5678,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
                                if (num > 0)
                                        fd = open(path, O_RDONLY, 0);
                                if ((num <= 0) || (fd < 0)) {
-                                       pr_vrb("Cannot open %s: %s\n",
+                                       pr_vrb("Cannot open %s: %s\n",
                                               dev->name, strerror(errno));
                                }
                                free(path);
@@ -5585,15 +5690,15 @@ 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 = xcalloc(1, sizeof(*dv));
-                                       dv->devname = xmalloc(strlen(memb->dev) + strlen("/dev/") + 1);
-                                       sprintf(dv->devname, "%s%s", "/dev/", memb->dev);
+                                       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;
@@ -5614,7 +5719,7 @@ 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 = xcalloc(1, sizeof(*dv));
@@ -5631,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;
@@ -5694,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.
@@ -5703,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;
        }
 
@@ -5716,7 +5821,7 @@ 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;
@@ -5878,8 +5983,7 @@ count_volumes(struct intel_hba *hba, int dpa, int verbose)
 
        devid_list = entry->devid_list;
        for (dv = devid_list; dv; dv = dv->next) {
-
-               struct md_list *devlist = NULL;
+               struct md_list *devlist;
                struct sys_dev *device = device_by_id(dv->devid);
                char *hba_path;
                int found = 0;
@@ -5889,6 +5993,14 @@ count_volumes(struct intel_hba *hba, int dpa, int verbose)
                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)
@@ -5935,14 +6047,14 @@ 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 */
        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;
        }
@@ -5951,24 +6063,24 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
                *chunk = imsm_default_chunk(super->orom);
 
        if (super->orom && !imsm_orom_has_chunk(super->orom, *chunk)) {
-               pr_vrb("platform does not support a chunk size of: %d\n", *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 &&
                        (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;
        }
 
@@ -6139,7 +6251,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                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;
                }
@@ -6295,7 +6407,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                                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;
                                }
@@ -7677,6 +7789,11 @@ 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
@@ -7805,7 +7922,8 @@ static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_
 
 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;
@@ -7814,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;
@@ -7840,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;
@@ -9150,7 +9269,7 @@ int validate_container_imsm(struct mdinfo *info)
                        return 1;
                }
 
-               if (orom != orom2) {
+               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;
@@ -9262,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;
@@ -9390,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;
@@ -9513,7 +9632,7 @@ static const char *imsm_get_disk_controller_domain(const char *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)
@@ -9678,11 +9797,11 @@ 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("(enter) raid_disks = %i\n", geo->raid_disks);
@@ -9759,8 +9878,8 @@ 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("(enter) New size = %llu\n", geo->size);
 
@@ -9789,8 +9908,8 @@ 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;
 
@@ -10249,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
@@ -10264,6 +10410,7 @@ exit_imsm_reshape_super:
 int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
 {
        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;
@@ -10274,11 +10421,17 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
                return 1;
        }
 
-       if (sysfs_fd_get_ll(fd, &completed) < 0) {
-               dprintf("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 > position_to_set) {
                dprintf("wrong next position to set %llu (%llu)\n",
@@ -10296,21 +10449,31 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
        }
 
        do {
+               int rc;
                char action[20];
-               sysfs_wait(fd, 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) {
+                               strncmp(action, "reshape", 7) != 0) {
+                       if (strncmp(action, "idle", 4) == 0)
+                               break;
+                       close(fd);
+                       return -1;
+               }
+
+               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;
-
 }
 
 /*******************************************************************************
@@ -10366,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
@@ -10390,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;
@@ -10408,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 */
@@ -10421,7 +10587,7 @@ static int imsm_manage_reshape(
        }
        /* Only one volume can migrate at the same time */
        if (migr_vol_qan != 1) {
-               pr_err("%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;
@@ -10496,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;
 
@@ -10510,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 */
@@ -10563,7 +10729,7 @@ 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;
                }
@@ -10601,7 +10767,10 @@ static int imsm_manage_reshape(
        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;
 }