diff options
author | NeilBrown <neilb@suse.com> | 2016-06-02 02:19:52 -0400 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2016-06-13 14:54:19 -0400 |
commit | e50d3992328320acf2454c1e7301a094cd90aebc (patch) | |
tree | 29b78f339a939f07ea4d10d7e8c953ca48bca360 | |
parent | 707a6a420ccf31634f2b15d8f06f09536e2de079 (diff) |
md/raid5: add rcu protection to rdev accesses in handle_failed_sync.
The rdev could be freed while handle_failed_sync is running, so
rcu protection is needed.
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | drivers/md/raid5.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index ad9e15a3ef51..e56c7e0627fa 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3210,15 +3210,16 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh, | |||
3210 | /* During recovery devices cannot be removed, so | 3210 | /* During recovery devices cannot be removed, so |
3211 | * locking and refcounting of rdevs is not needed | 3211 | * locking and refcounting of rdevs is not needed |
3212 | */ | 3212 | */ |
3213 | rcu_read_lock(); | ||
3213 | for (i = 0; i < conf->raid_disks; i++) { | 3214 | for (i = 0; i < conf->raid_disks; i++) { |
3214 | struct md_rdev *rdev = conf->disks[i].rdev; | 3215 | struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); |
3215 | if (rdev | 3216 | if (rdev |
3216 | && !test_bit(Faulty, &rdev->flags) | 3217 | && !test_bit(Faulty, &rdev->flags) |
3217 | && !test_bit(In_sync, &rdev->flags) | 3218 | && !test_bit(In_sync, &rdev->flags) |
3218 | && !rdev_set_badblocks(rdev, sh->sector, | 3219 | && !rdev_set_badblocks(rdev, sh->sector, |
3219 | STRIPE_SECTORS, 0)) | 3220 | STRIPE_SECTORS, 0)) |
3220 | abort = 1; | 3221 | abort = 1; |
3221 | rdev = conf->disks[i].replacement; | 3222 | rdev = rcu_dereference(conf->disks[i].replacement); |
3222 | if (rdev | 3223 | if (rdev |
3223 | && !test_bit(Faulty, &rdev->flags) | 3224 | && !test_bit(Faulty, &rdev->flags) |
3224 | && !test_bit(In_sync, &rdev->flags) | 3225 | && !test_bit(In_sync, &rdev->flags) |
@@ -3226,6 +3227,7 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh, | |||
3226 | STRIPE_SECTORS, 0)) | 3227 | STRIPE_SECTORS, 0)) |
3227 | abort = 1; | 3228 | abort = 1; |
3228 | } | 3229 | } |
3230 | rcu_read_unlock(); | ||
3229 | if (abort) | 3231 | if (abort) |
3230 | conf->recovery_disabled = | 3232 | conf->recovery_disabled = |
3231 | conf->mddev->recovery_disabled; | 3233 | conf->mddev->recovery_disabled; |