diff options
author | NeilBrown <neilb@suse.de> | 2006-10-03 04:15:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:18 -0400 |
commit | c04be0aa82ff535e3676ab3e573957bdeef41879 (patch) | |
tree | 8481ab270218bed246eb02b3ba04a4b84d4e90d0 /drivers/md/raid1.c | |
parent | 11ce99e625fe2718ad2682bfdd99070b337e6252 (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.c | 16 |
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 | ||