Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 725d6e57 authored by NeilBrown's avatar NeilBrown
Browse files

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: default avatarNeilBrown <neilb@suse.de>
parent 635f6416
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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)