aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-03 04:15:53 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:18 -0400
commitc04be0aa82ff535e3676ab3e573957bdeef41879 (patch)
tree8481ab270218bed246eb02b3ba04a4b84d4e90d0 /drivers/md/raid5.c
parent11ce99e625fe2718ad2682bfdd99070b337e6252 (diff)
[PATCH] md: Improve locking around error handling
The error handling routines don't use proper locking, and so two concurrent errors could trigger a problem. So: - use test-and-set and test-and-clear to synchonise the In_sync bits with the ->degraded count - use the spinlock to protect updates to the degraded count (could use an atomic_t but that would be a bigger change in code, and isn't really justified) - remove un-necessary locking in raid5 Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 46fd651539fe..6cea9c9a98e2 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -636,7 +636,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
636 struct stripe_head *sh = bi->bi_private; 636 struct stripe_head *sh = bi->bi_private;
637 raid5_conf_t *conf = sh->raid_conf; 637 raid5_conf_t *conf = sh->raid_conf;
638 int disks = sh->disks, i; 638 int disks = sh->disks, i;
639 unsigned long flags;
640 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); 639 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
641 640
642 if (bi->bi_size) 641 if (bi->bi_size)
@@ -654,7 +653,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
654 return 0; 653 return 0;
655 } 654 }
656 655
657 spin_lock_irqsave(&conf->device_lock, flags);
658 if (!uptodate) 656 if (!uptodate)
659 md_error(conf->mddev, conf->disks[i].rdev); 657 md_error(conf->mddev, conf->disks[i].rdev);
660 658
@@ -662,8 +660,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
662 660
663 clear_bit(R5_LOCKED, &sh->dev[i].flags); 661 clear_bit(R5_LOCKED, &sh->dev[i].flags);
664 set_bit(STRIPE_HANDLE, &sh->state); 662 set_bit(STRIPE_HANDLE, &sh->state);
665 __release_stripe(conf, sh); 663 release_stripe(sh);
666 spin_unlock_irqrestore(&conf->device_lock, flags);
667 return 0; 664 return 0;
668} 665}
669 666
@@ -697,9 +694,11 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
697 694
698 if (!test_bit(Faulty, &rdev->flags)) { 695 if (!test_bit(Faulty, &rdev->flags)) {
699 set_bit(MD_CHANGE_DEVS, &mddev->flags); 696 set_bit(MD_CHANGE_DEVS, &mddev->flags);
700 if (test_bit(In_sync, &rdev->flags)) { 697 if (test_and_clear_bit(In_sync, &rdev->flags)) {
698 unsigned long flags;
699 spin_lock_irqsave(&conf->device_lock, flags);
701 mddev->degraded++; 700 mddev->degraded++;
702 clear_bit(In_sync, &rdev->flags); 701 spin_unlock_irqrestore(&conf->device_lock, flags);
703 /* 702 /*
704 * if recovery was running, make sure it aborts. 703 * if recovery was running, make sure it aborts.
705 */ 704 */
@@ -3418,9 +3417,11 @@ static int raid5_spare_active(mddev_t *mddev)
3418 tmp = conf->disks + i; 3417 tmp = conf->disks + i;
3419 if (tmp->rdev 3418 if (tmp->rdev
3420 && !test_bit(Faulty, &tmp->rdev->flags) 3419 && !test_bit(Faulty, &tmp->rdev->flags)
3421 && !test_bit(In_sync, &tmp->rdev->flags)) { 3420 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
3421 unsigned long flags;
3422 spin_lock_irqsave(&conf->device_lock, flags);
3422 mddev->degraded--; 3423 mddev->degraded--;
3423 set_bit(In_sync, &tmp->rdev->flags); 3424 spin_unlock_irqrestore(&conf->device_lock, flags);
3424 } 3425 }
3425 } 3426 }
3426 print_raid5_conf(conf); 3427 print_raid5_conf(conf);
@@ -3556,6 +3557,7 @@ static int raid5_start_reshape(mddev_t *mddev)
3556 struct list_head *rtmp; 3557 struct list_head *rtmp;
3557 int spares = 0; 3558 int spares = 0;
3558 int added_devices = 0; 3559 int added_devices = 0;
3560 unsigned long flags;
3559 3561
3560 if (mddev->degraded || 3562 if (mddev->degraded ||
3561 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) 3563 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3597,7 +3599,9 @@ static int raid5_start_reshape(mddev_t *mddev)
3597 break; 3599 break;
3598 } 3600 }
3599 3601
3602 spin_lock_irqsave(&conf->device_lock, flags);
3600 mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices; 3603 mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
3604 spin_unlock_irqrestore(&conf->device_lock, flags);
3601 mddev->raid_disks = conf->raid_disks; 3605 mddev->raid_disks = conf->raid_disks;
3602 mddev->reshape_position = 0; 3606 mddev->reshape_position = 0;
3603 set_bit(MD_CHANGE_DEVS, &mddev->flags); 3607 set_bit(MD_CHANGE_DEVS, &mddev->flags);