imsm: FIX: Check maximum allowed degradation level in open_backup_targets()

Any degradation during opening any backup device can causes error
and array assembly failure.

Allow for degradation during opening backup devices.
This allows for degraded array assembly.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Adam Kwolek 2011-12-06 11:39:58 +11:00 committed by NeilBrown
parent d598513843
commit 9a7172822a
1 changed files with 90 additions and 7 deletions

View File

@ -8018,6 +8018,75 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
}
}
#endif /* MDASSEMBLE */
static void close_targets(int *targets, int new_disks)
{
int i;
if (!targets)
return;
for (i = 0; i < new_disks; i++) {
if (targets[i] >= 0) {
close(targets[i]);
targets[i] = -1;
}
}
}
static int imsm_get_allowed_degradation(int level, int raid_disks,
struct intel_super *super,
struct imsm_dev *dev)
{
switch (level) {
case 10:{
int ret_val = 0;
struct imsm_map *map;
int i;
ret_val = raid_disks/2;
/* check map if all disks pairs not failed
* in both maps
*/
map = get_imsm_map(dev, 0);
for (i = 0; i < ret_val; i++) {
int degradation = 0;
if (get_imsm_disk(super, i) == NULL)
degradation++;
if (get_imsm_disk(super, i + 1) == NULL)
degradation++;
if (degradation == 2)
return 0;
}
map = get_imsm_map(dev, 1);
/* if there is no second map
* result can be returned
*/
if (map == NULL)
return ret_val;
/* check degradation in second map
*/
for (i = 0; i < ret_val; i++) {
int degradation = 0;
if (get_imsm_disk(super, i) == NULL)
degradation++;
if (get_imsm_disk(super, i + 1) == NULL)
degradation++;
if (degradation == 2)
return 0;
}
return ret_val;
}
case 5:
return 1;
case 6:
return 2;
default:
return 0;
}
}
/*******************************************************************************
* Function: open_backup_targets
* Description: Function opens file descriptors for all devices given in
@ -8026,14 +8095,18 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
* info : general array info
* raid_disks : number of disks
* raid_fds : table of device's file descriptors
* super : intel super for raid10 degradation check
* dev : intel device for raid10 degradation check
* Returns:
* 0 : success
* -1 : fail
******************************************************************************/
int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds)
int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
struct intel_super *super, struct imsm_dev *dev)
{
struct mdinfo *sd;
int i;
int opened = 0;
for (i = 0; i < raid_disks; i++)
raid_fds[i] = -1;
@ -8055,8 +8128,19 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds)
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");
return -1;
continue;
}
opened++;
}
/* check if maximum array degradation level is not exceeded
*/
if ((raid_disks - opened) >
imsm_get_allowed_degradation(info->new_level,
raid_disks,
super, dev)) {
fprintf(stderr, "Not enough disks can be opened.\n");
close_targets(raid_fds, raid_disks);
return -2;
}
return 0;
}
@ -8189,7 +8273,8 @@ int save_backup_imsm(struct supertype *st,
target_offsets[i] -= start/data_disks;
}
if (open_backup_targets(info, new_disks, targets))
if (open_backup_targets(info, new_disks, targets,
super, dev))
goto abort;
dest_layout = imsm_level_to_layout(map_dest->raid_level);
@ -8215,9 +8300,7 @@ int save_backup_imsm(struct supertype *st,
abort:
if (targets) {
for (i = 0; i < new_disks; i++)
if (targets[i] >= 0)
close(targets[i]);
close_targets(targets, new_disks);
free(targets);
}
free(target_offsets);
@ -8346,7 +8429,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
if (!targets)
goto abort;
if (open_backup_targets(info, new_disks, targets)) {
if (open_backup_targets(info, new_disks, targets, super, id->dev)) {
fprintf(stderr,
Name ": Cannot open some devices belonging to array.\n");
goto abort;