aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2016-06-02 02:19:52 -0400
committerShaohua Li <shli@fb.com>2016-06-13 14:54:19 -0400
commite50d3992328320acf2454c1e7301a094cd90aebc (patch)
tree29b78f339a939f07ea4d10d7e8c953ca48bca360
parent707a6a420ccf31634f2b15d8f06f09536e2de079 (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.c6
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;