aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.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/raid10.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/raid10.c')
-rw-r--r--drivers/md/raid10.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 233a4faede94..64f8016ab740 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -950,14 +950,16 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
950 * really dead" tests... 950 * really dead" tests...
951 */ 951 */
952 return; 952 return;
953 if (test_bit(In_sync, &rdev->flags)) { 953 if (test_and_clear_bit(In_sync, &rdev->flags)) {
954 unsigned long flags;
955 spin_lock_irqsave(&conf->device_lock, flags);
954 mddev->degraded++; 956 mddev->degraded++;
957 spin_unlock_irqrestore(&conf->device_lock, flags);
955 /* 958 /*
956 * if recovery is running, make sure it aborts. 959 * if recovery is running, make sure it aborts.
957 */ 960 */
958 set_bit(MD_RECOVERY_ERR, &mddev->recovery); 961 set_bit(MD_RECOVERY_ERR, &mddev->recovery);
959 } 962 }
960 clear_bit(In_sync, &rdev->flags);
961 set_bit(Faulty, &rdev->flags); 963 set_bit(Faulty, &rdev->flags);
962 set_bit(MD_CHANGE_DEVS, &mddev->flags); 964 set_bit(MD_CHANGE_DEVS, &mddev->flags);
963 printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n" 965 printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
@@ -1033,9 +1035,11 @@ static int raid10_spare_active(mddev_t *mddev)
1033 tmp = conf->mirrors + i; 1035 tmp = conf->mirrors + i;
1034 if (tmp->rdev 1036 if (tmp->rdev
1035 && !test_bit(Faulty, &tmp->rdev->flags) 1037 && !test_bit(Faulty, &tmp->rdev->flags)
1036 && !test_bit(In_sync, &tmp->rdev->flags)) { 1038 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
1039 unsigned long flags;
1040 spin_lock_irqsave(&conf->device_lock, flags);
1037 mddev->degraded--; 1041 mddev->degraded--;
1038 set_bit(In_sync, &tmp->rdev->flags); 1042 spin_unlock_irqrestore(&conf->device_lock, flags);
1039 } 1043 }
1040 } 1044 }
1041 1045