aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-12-22 18:17:50 -0500
committerNeilBrown <neilb@suse.de>2011-12-22 18:17:50 -0500
commit908f4fbd265733310c17ecc906299846b5dac44a (patch)
tree71e364c57887213431143e6fd1296e8433cc6293 /drivers/md
parent2e61ebbcc45438899235d7a39f17291cb24e746c (diff)
md/raid5: be more thorough in calculating 'degraded' value.
When an array is being reshaped to change the number of devices, the two halves can be differently degraded. e.g. one could be missing a device and the other not. So we need to be more careful about calculating the 'degraded' attribute. Instead of just inc/dec at appropriate times, perform a full re-calculation examining both possible cases. This doesn't happen often so it not a big cost, and we already have most of the code to do it. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid5.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 858fdbb7eb07..a68c49250ed5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -370,12 +370,10 @@ static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
370 * of the two sections, and some non-in_sync devices may 370 * of the two sections, and some non-in_sync devices may
371 * be insync in the section most affected by failed devices. 371 * be insync in the section most affected by failed devices.
372 */ 372 */
373static int has_failed(struct r5conf *conf) 373static int calc_degraded(struct r5conf *conf)
374{ 374{
375 int degraded; 375 int degraded, degraded2;
376 int i; 376 int i;
377 if (conf->mddev->reshape_position == MaxSector)
378 return conf->mddev->degraded > conf->max_degraded;
379 377
380 rcu_read_lock(); 378 rcu_read_lock();
381 degraded = 0; 379 degraded = 0;
@@ -399,14 +397,14 @@ static int has_failed(struct r5conf *conf)
399 degraded++; 397 degraded++;
400 } 398 }
401 rcu_read_unlock(); 399 rcu_read_unlock();
402 if (degraded > conf->max_degraded) 400 if (conf->raid_disks == conf->previous_raid_disks)
403 return 1; 401 return degraded;
404 rcu_read_lock(); 402 rcu_read_lock();
405 degraded = 0; 403 degraded2 = 0;
406 for (i = 0; i < conf->raid_disks; i++) { 404 for (i = 0; i < conf->raid_disks; i++) {
407 struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); 405 struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
408 if (!rdev || test_bit(Faulty, &rdev->flags)) 406 if (!rdev || test_bit(Faulty, &rdev->flags))
409 degraded++; 407 degraded2++;
410 else if (test_bit(In_sync, &rdev->flags)) 408 else if (test_bit(In_sync, &rdev->flags))
411 ; 409 ;
412 else 410 else
@@ -416,9 +414,22 @@ static int has_failed(struct r5conf *conf)
416 * almost certainly hasn't. 414 * almost certainly hasn't.
417 */ 415 */
418 if (conf->raid_disks <= conf->previous_raid_disks) 416 if (conf->raid_disks <= conf->previous_raid_disks)
419 degraded++; 417 degraded2++;
420 } 418 }
421 rcu_read_unlock(); 419 rcu_read_unlock();
420 if (degraded2 > degraded)
421 return degraded2;
422 return degraded;
423}
424
425static int has_failed(struct r5conf *conf)
426{
427 int degraded;
428
429 if (conf->mddev->reshape_position == MaxSector)
430 return conf->mddev->degraded > conf->max_degraded;
431
432 degraded = calc_degraded(conf);
422 if (degraded > conf->max_degraded) 433 if (degraded > conf->max_degraded)
423 return 1; 434 return 1;
424 return 0; 435 return 0;
@@ -1724,18 +1735,15 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
1724{ 1735{
1725 char b[BDEVNAME_SIZE]; 1736 char b[BDEVNAME_SIZE];
1726 struct r5conf *conf = mddev->private; 1737 struct r5conf *conf = mddev->private;
1738 unsigned long flags;
1727 pr_debug("raid456: error called\n"); 1739 pr_debug("raid456: error called\n");
1728 1740
1729 if (test_and_clear_bit(In_sync, &rdev->flags)) { 1741 spin_lock_irqsave(&conf->device_lock, flags);
1730 unsigned long flags; 1742 clear_bit(In_sync, &rdev->flags);
1731 spin_lock_irqsave(&conf->device_lock, flags); 1743 mddev->degraded = calc_degraded(conf);
1732 mddev->degraded++; 1744 spin_unlock_irqrestore(&conf->device_lock, flags);
1733 spin_unlock_irqrestore(&conf->device_lock, flags); 1745 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
1734 /* 1746
1735 * if recovery was running, make sure it aborts.
1736 */
1737 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
1738 }
1739 set_bit(Blocked, &rdev->flags); 1747 set_bit(Blocked, &rdev->flags);
1740 set_bit(Faulty, &rdev->flags); 1748 set_bit(Faulty, &rdev->flags);
1741 set_bit(MD_CHANGE_DEVS, &mddev->flags); 1749 set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -4852,8 +4860,7 @@ static int run(struct mddev *mddev)
4852 dirty_parity_disks++; 4860 dirty_parity_disks++;
4853 } 4861 }
4854 4862
4855 mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks) 4863 mddev->degraded = calc_degraded(conf);
4856 - working_disks);
4857 4864
4858 if (has_failed(conf)) { 4865 if (has_failed(conf)) {
4859 printk(KERN_ERR "md/raid:%s: not enough operational devices" 4866 printk(KERN_ERR "md/raid:%s: not enough operational devices"
@@ -5025,7 +5032,7 @@ static int raid5_spare_active(struct mddev *mddev)
5025 } 5032 }
5026 } 5033 }
5027 spin_lock_irqsave(&conf->device_lock, flags); 5034 spin_lock_irqsave(&conf->device_lock, flags);
5028 mddev->degraded -= count; 5035 mddev->degraded = calc_degraded(conf);
5029 spin_unlock_irqrestore(&conf->device_lock, flags); 5036 spin_unlock_irqrestore(&conf->device_lock, flags);
5030 print_raid5_conf(conf); 5037 print_raid5_conf(conf);
5031 return count; 5038 return count;
@@ -5286,8 +5293,7 @@ static int raid5_start_reshape(struct mddev *mddev)
5286 * pre and post number of devices. 5293 * pre and post number of devices.
5287 */ 5294 */
5288 spin_lock_irqsave(&conf->device_lock, flags); 5295 spin_lock_irqsave(&conf->device_lock, flags);
5289 mddev->degraded += (conf->raid_disks - conf->previous_raid_disks) 5296 mddev->degraded = calc_degraded(conf);
5290 - added_devices;
5291 spin_unlock_irqrestore(&conf->device_lock, flags); 5297 spin_unlock_irqrestore(&conf->device_lock, flags);
5292 } 5298 }
5293 mddev->raid_disks = conf->raid_disks; 5299 mddev->raid_disks = conf->raid_disks;
@@ -5356,12 +5362,9 @@ static void raid5_finish_reshape(struct mddev *mddev)
5356 revalidate_disk(mddev->gendisk); 5362 revalidate_disk(mddev->gendisk);
5357 } else { 5363 } else {
5358 int d; 5364 int d;
5359 mddev->degraded = conf->raid_disks; 5365 spin_lock_irq(&conf->device_lock);
5360 for (d = 0; d < conf->raid_disks ; d++) 5366 mddev->degraded = calc_degraded(conf);
5361 if (conf->disks[d].rdev && 5367 spin_unlock_irq(&conf->device_lock);
5362 test_bit(In_sync,
5363 &conf->disks[d].rdev->flags))
5364 mddev->degraded--;
5365 for (d = conf->raid_disks ; 5368 for (d = conf->raid_disks ;
5366 d < conf->raid_disks - mddev->delta_disks; 5369 d < conf->raid_disks - mddev->delta_disks;
5367 d++) { 5370 d++) {