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

Commit 17045f52 authored by NeilBrown's avatar NeilBrown
Browse files

md/raid5: recognise replacements when assembling array.



If a Replacement is seen, file it as such.

If we see two replacements (or two normal devices) for the one slot,
abort.

Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent dd054fce
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -4847,7 +4847,15 @@ static struct r5conf *setup_conf(struct mddev *mddev)
			continue;
		disk = conf->disks + raid_disk;

		if (test_bit(Replacement, &rdev->flags)) {
			if (disk->replacement)
				goto abort;
			disk->replacement = rdev;
		} else {
			if (disk->rdev)
				goto abort;
			disk->rdev = rdev;
		}

		if (test_bit(In_sync, &rdev->flags)) {
			char b[BDEVNAME_SIZE];
@@ -4936,6 +4944,7 @@ static int run(struct mddev *mddev)
	int dirty_parity_disks = 0;
	struct md_rdev *rdev;
	sector_t reshape_offset = 0;
	int i;

	if (mddev->recovery_cp != MaxSector)
		printk(KERN_NOTICE "md/raid:%s: not clean"
@@ -5025,12 +5034,25 @@ static int run(struct mddev *mddev)
	conf->thread = NULL;
	mddev->private = conf;

	/*
	 * 0 for a fully functional array, 1 or 2 for a degraded array.
	 */
	list_for_each_entry(rdev, &mddev->disks, same_set) {
		if (rdev->raid_disk < 0)
	for (i = 0; i < conf->raid_disks && conf->previous_raid_disks;
	     i++) {
		rdev = conf->disks[i].rdev;
		if (!rdev && conf->disks[i].replacement) {
			/* The replacement is all we have yet */
			rdev = conf->disks[i].replacement;
			conf->disks[i].replacement = NULL;
			clear_bit(Replacement, &rdev->flags);
			conf->disks[i].rdev = rdev;
		}
		if (!rdev)
			continue;
		if (conf->disks[i].replacement &&
		    conf->reshape_progress != MaxSector) {
			/* replacements and reshape simply do not mix. */
			printk(KERN_ERR "md: cannot handle concurrent "
			       "replacement and reshape.\n");
			goto abort;
		}
		if (test_bit(In_sync, &rdev->flags)) {
			working_disks++;
			continue;
@@ -5064,6 +5086,9 @@ static int run(struct mddev *mddev)
		dirty_parity_disks++;
	}

	/*
	 * 0 for a fully functional array, 1 or 2 for a degraded array.
	 */
	mddev->degraded = calc_degraded(conf);

	if (has_failed(conf)) {