aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid1.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/raid1.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/raid1.c')
-rw-r--r--drivers/md/raid1.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 3fc9ec239478..99c4e031c7f1 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -959,14 +959,16 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
959 * normal single drive 959 * normal single drive
960 */ 960 */
961 return; 961 return;
962 if (test_bit(In_sync, &rdev->flags)) { 962 if (test_and_clear_bit(In_sync, &rdev->flags)) {
963 unsigned long flags;
964 spin_lock_irqsave(&conf->device_lock, flags);
963 mddev->degraded++; 965 mddev->degraded++;
966 spin_unlock_irqrestore(&conf->device_lock, flags);
964 /* 967 /*
965 * if recovery is running, make sure it aborts. 968 * if recovery is running, make sure it aborts.
966 */ 969 */
967 set_bit(MD_RECOVERY_ERR, &mddev->recovery); 970 set_bit(MD_RECOVERY_ERR, &mddev->recovery);
968 } 971 }
969 clear_bit(In_sync, &rdev->flags);
970 set_bit(Faulty, &rdev->flags); 972 set_bit(Faulty, &rdev->flags);
971 set_bit(MD_CHANGE_DEVS, &mddev->flags); 973 set_bit(MD_CHANGE_DEVS, &mddev->flags);
972 printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" 974 printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n"
@@ -1022,9 +1024,11 @@ static int raid1_spare_active(mddev_t *mddev)
1022 mdk_rdev_t *rdev = conf->mirrors[i].rdev; 1024 mdk_rdev_t *rdev = conf->mirrors[i].rdev;
1023 if (rdev 1025 if (rdev
1024 && !test_bit(Faulty, &rdev->flags) 1026 && !test_bit(Faulty, &rdev->flags)
1025 && !test_bit(In_sync, &rdev->flags)) { 1027 && !test_and_set_bit(In_sync, &rdev->flags)) {
1028 unsigned long flags;
1029 spin_lock_irqsave(&conf->device_lock, flags);
1026 mddev->degraded--; 1030 mddev->degraded--;
1027 set_bit(In_sync, &rdev->flags); 1031 spin_unlock_irqrestore(&conf->device_lock, flags);
1028 } 1032 }
1029 } 1033 }
1030 1034
@@ -2048,7 +2052,7 @@ static int raid1_reshape(mddev_t *mddev)
2048 mirror_info_t *newmirrors; 2052 mirror_info_t *newmirrors;
2049 conf_t *conf = mddev_to_conf(mddev); 2053 conf_t *conf = mddev_to_conf(mddev);
2050 int cnt, raid_disks; 2054 int cnt, raid_disks;
2051 2055 unsigned long flags;
2052 int d, d2; 2056 int d, d2;
2053 2057
2054 /* Cannot change chunk_size, layout, or level */ 2058 /* Cannot change chunk_size, layout, or level */
@@ -2107,7 +2111,9 @@ static int raid1_reshape(mddev_t *mddev)
2107 kfree(conf->poolinfo); 2111 kfree(conf->poolinfo);
2108 conf->poolinfo = newpoolinfo; 2112 conf->poolinfo = newpoolinfo;
2109 2113
2114 spin_lock_irqsave(&conf->device_lock, flags);
2110 mddev->degraded += (raid_disks - conf->raid_disks); 2115 mddev->degraded += (raid_disks - conf->raid_disks);
2116 spin_unlock_irqrestore(&conf->device_lock, flags);
2111 conf->raid_disks = mddev->raid_disks = raid_disks; 2117 conf->raid_disks = mddev->raid_disks = raid_disks;
2112 mddev->delta_disks = 0; 2118 mddev->delta_disks = 0;
2113 2119