diff options
author | NeilBrown <neilb@suse.com> | 2016-06-02 16:19:52 +1000 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2016-06-13 11:54:19 -0700 |
commit | e50d3992328320acf2454c1e7301a094cd90aebc (patch) | |
tree | 29b78f339a939f07ea4d10d7e8c953ca48bca360 /drivers/md | |
parent | 707a6a420ccf31634f2b15d8f06f09536e2de079 (diff) | |
download | op-kernel-dev-e50d3992328320acf2454c1e7301a094cd90aebc.zip op-kernel-dev-e50d3992328320acf2454c1e7301a094cd90aebc.tar.gz |
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>
Diffstat (limited to 'drivers/md')
-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 ad9e15a..e56c7e0 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, /* During recovery devices cannot be removed, so * locking and refcounting of rdevs is not needed */ + rcu_read_lock(); for (i = 0; i < conf->raid_disks; i++) { - struct md_rdev *rdev = conf->disks[i].rdev; + struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) && !rdev_set_badblocks(rdev, sh->sector, STRIPE_SECTORS, 0)) abort = 1; - rdev = conf->disks[i].replacement; + rdev = rcu_dereference(conf->disks[i].replacement); if (rdev && !test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags) @@ -3226,6 +3227,7 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh, STRIPE_SECTORS, 0)) abort = 1; } + rcu_read_unlock(); if (abort) conf->recovery_disabled = conf->mddev->recovery_disabled; |