md/raid5: add rcu protection to rdev accesses in handle_failed_sync.
authorNeilBrown <neilb@suse.com>
Thu, 2 Jun 2016 06:19:52 +0000 (16:19 +1000)
committerShaohua Li <shli@fb.com>
Mon, 13 Jun 2016 18:54:19 +0000 (11:54 -0700)
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>
drivers/md/raid5.c

index ad9e15a..e56c7e0 100644 (file)
@@ -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;