summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Kwolek <adam.kwolek@intel.com>2011-06-09 13:00:55 +1000
committerNeilBrown <neilb@suse.de>2011-06-09 13:00:55 +1000
commit6c3560c0f2e16bafa2899cd1ca4df78ba9512170 (patch)
tree6b675fc7b057819ecc7098fc9bfec8eb9bd04787
parentab724b9862d7a8c4d85ed4b19be87ba9768a2432 (diff)
downloadmdadm-6c3560c0f2e16bafa2899cd1ca4df78ba9512170.tar.gz
imsm: FIX: Detect failed devices during recover_backup_imsm()
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>
-rw-r--r--super-intel.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/super-intel.c b/super-intel.c
index a459fb0..d897900 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -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++;