Skip to content

Commit 725d6e5

Browse files
committed
md/raid10: check In_sync flag in 'enough()'.
It isn't really enough to check that the rdev is present, we need to also be sure that the device is still In_sync. Doing this requires using rcu_dereference to access the rdev, and holding the rcu_read_lock() to ensure the rdev doesn't disappear while we look at it. Signed-off-by: NeilBrown <[email protected]>
1 parent 635f641 commit 725d6e5

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

drivers/md/raid10.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ static void status(struct seq_file *seq, struct mddev *mddev)
16331633
static int _enough(struct r10conf *conf, int previous, int ignore)
16341634
{
16351635
int first = 0;
1636+
int has_enough = 0;
16361637
int disks, ncopies;
16371638
if (previous) {
16381639
disks = conf->prev.raid_disks;
@@ -1642,21 +1643,27 @@ static int _enough(struct r10conf *conf, int previous, int ignore)
16421643
ncopies = conf->geo.near_copies;
16431644
}
16441645

1646+
rcu_read_lock();
16451647
do {
16461648
int n = conf->copies;
16471649
int cnt = 0;
16481650
int this = first;
16491651
while (n--) {
1650-
if (conf->mirrors[this].rdev &&
1651-
this != ignore)
1652+
struct md_rdev *rdev;
1653+
if (this != ignore &&
1654+
(rdev = rcu_dereference(conf->mirrors[this].rdev)) &&
1655+
test_bit(In_sync, &rdev->flags))
16521656
cnt++;
16531657
this = (this+1) % disks;
16541658
}
16551659
if (cnt == 0)
1656-
return 0;
1660+
goto out;
16571661
first = (first + ncopies) % disks;
16581662
} while (first != 0);
1659-
return 1;
1663+
has_enough = 1;
1664+
out:
1665+
rcu_read_unlock();
1666+
return has_enough;
16601667
}
16611668

16621669
static int enough(struct r10conf *conf, int ignore)

0 commit comments

Comments
 (0)