]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: FIX: Detect failed devices during recover_backup_imsm()
authorAdam Kwolek <adam.kwolek@intel.com>
Thu, 9 Jun 2011 03:00:55 +0000 (13:00 +1000)
committerNeilBrown <neilb@suse.de>
Thu, 9 Jun 2011 03:00:55 +0000 (13:00 +1000)
Detect in recover_backup_imsm() if not opened disks number is smaller
than allowed degradation for given raid level. This allows for reshape restart
on degraded array.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
super-intel.c

index a459fb0d3a50b6ebb0f8bb337dbdfc64c54d0c66..d897900d8efb05abdaa0861460ae072bc0dd9ee3 100644 (file)
@@ -7825,6 +7825,8 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
        unsigned long num_migr_units = __le32_to_cpu(migr_rec->num_migr_units);
        int ascending = __le32_to_cpu(migr_rec->ascending_migr);
        char buffer[20];
+       int skipped_disks = 0;
+       int max_degradation;
 
        err = sysfs_get_str(info, NULL, "array_state", (char *)buffer, 20);
        if (err < 1)
@@ -7848,6 +7850,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
 
        map_dest = get_imsm_map(id->dev, 0);
        new_disks = map_dest->num_members;
+       max_degradation = new_disks - imsm_num_data_members(id->dev, 0);
 
        read_offset = (unsigned long long)
                        __le32_to_cpu(migr_rec->ckpt_area_pba) * 512;
@@ -7866,6 +7869,10 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
        open_backup_targets(info, new_disks, targets);
 
        for (i = 0; i < new_disks; i++) {
+               if (targets[i] < 0) {
+                       skipped_disks++;
+                       continue;
+               }
                if (lseek64(targets[i], read_offset, SEEK_SET) < 0) {
                        fprintf(stderr,
                                Name ": Cannot seek to block: %s\n",
@@ -7892,6 +7899,13 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
                }
        }
 
+       if (skipped_disks > max_degradation) {
+               fprintf(stderr,
+                       Name ": Cannot restore data from backup."
+                       " Too many failed disks\n");
+               goto abort;
+       }
+
        if (ascending && curr_migr_unit < (num_migr_units-1))
                curr_migr_unit++;