Skip to content

Commit

Permalink
md/raid10: check In_sync flag in 'enough()'.
Browse files Browse the repository at this point in the history
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 <neilb@suse.de>
  • Loading branch information
NeilBrown committed Jun 13, 2013
1 parent 635f641 commit 725d6e5
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,7 @@ static void status(struct seq_file *seq, struct mddev *mddev)
static int _enough(struct r10conf *conf, int previous, int ignore)
{
int first = 0;
int has_enough = 0;
int disks, ncopies;
if (previous) {
disks = conf->prev.raid_disks;
Expand All @@ -1642,21 +1643,27 @@ static int _enough(struct r10conf *conf, int previous, int ignore)
ncopies = conf->geo.near_copies;
}

rcu_read_lock();
do {
int n = conf->copies;
int cnt = 0;
int this = first;
while (n--) {
if (conf->mirrors[this].rdev &&
this != ignore)
struct md_rdev *rdev;
if (this != ignore &&
(rdev = rcu_dereference(conf->mirrors[this].rdev)) &&
test_bit(In_sync, &rdev->flags))
cnt++;
this = (this+1) % disks;
}
if (cnt == 0)
return 0;
goto out;
first = (first + ncopies) % disks;
} while (first != 0);
return 1;
has_enough = 1;
out:
rcu_read_unlock();
return has_enough;
}

static int enough(struct r10conf *conf, int ignore)
Expand Down

0 comments on commit 725d6e5

Please sign in to comment.