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

Commit f94d4fe0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'md-3.8-fixes' of git://neil.brown.name/md

Pull dmraid fix from NeilBrown:
 "Just one fix for md in 3.8

  dmraid assess redundancy and replacements slightly inaccurately which
  could lead to some degraded arrays failing to assemble."

* tag 'md-3.8-fixes' of git://neil.brown.name/md:
  DM-RAID: Fix RAID10's check for sufficient redundancy
parents 45e72af0 55ebbb59
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -141,3 +141,4 @@ Version History
1.2.0	Handle creation of arrays that contain failed devices.
1.3.0	Added support for RAID 10
1.3.1	Allow device replacement/rebuild for RAID 10
1.3.2   Fix/improve redundancy checking for RAID10
+37 −64
Original line number Diff line number Diff line
@@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
}

/*
 * validate_rebuild_devices
 * validate_raid_redundancy
 * @rs
 *
 * Determine if the devices specified for rebuild can result in a valid
 * usable array that is capable of rebuilding the given devices.
 * Determine if there are enough devices in the array that haven't
 * failed (or are being rebuilt) to form a usable array.
 *
 * Returns: 0 on success, -EINVAL on failure.
 */
static int validate_rebuild_devices(struct raid_set *rs)
static int validate_raid_redundancy(struct raid_set *rs)
{
	unsigned i, rebuild_cnt = 0;
	unsigned rebuilds_per_group, copies, d;

	if (!(rs->print_flags & DMPF_REBUILD))
		return 0;

	for (i = 0; i < rs->md.raid_disks; i++)
		if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
		if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
		    !rs->dev[i].rdev.sb_page)
			rebuild_cnt++;

	switch (rs->raid_type->level) {
@@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs)
		 *          A    A    B    B    C
		 *          C    D    D    E    E
		 */
		rebuilds_per_group = 0;
		for (i = 0; i < rs->md.raid_disks * copies; i++) {
			if (!(i % copies))
				rebuilds_per_group = 0;
			d = i % rs->md.raid_disks;
			if (!test_bit(In_sync, &rs->dev[d].rdev.flags) &&
			if ((!rs->dev[d].rdev.sb_page ||
			     !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
			    (++rebuilds_per_group >= copies))
				goto too_many;
			if (!((i + 1) % copies))
				rebuilds_per_group = 0;
		}
		break;
	default:
		DMERR("The rebuild parameter is not supported for %s",
		      rs->raid_type->name);
		rs->ti->error = "Rebuild not supported for this RAID type";
		if (rebuild_cnt)
			return -EINVAL;
	}

	return 0;

too_many:
	rs->ti->error = "Too many rebuild devices specified";
	return -EINVAL;
}

@@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
	}
	rs->md.dev_sectors = sectors_per_dev;

	if (validate_rebuild_devices(rs))
		return -EINVAL;

	/* Assume there are no metadata devices until the drives are parsed */
	rs->md.persistent = 0;
	rs->md.external = 1;
@@ -995,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
{
	int ret;
	unsigned redundancy = 0;
	struct raid_dev *dev;
	struct md_rdev *rdev, *tmp, *freshest;
	struct mddev *mddev = &rs->md;

	switch (rs->raid_type->level) {
	case 1:
		redundancy = rs->md.raid_disks - 1;
		break;
	case 4:
	case 5:
	case 6:
		redundancy = rs->raid_type->parity_devs;
		break;
	case 10:
		redundancy = raid10_md_layout_to_copies(mddev->layout) - 1;
		break;
	default:
		ti->error = "Unknown RAID type";
		return -EINVAL;
	}

	freshest = NULL;
	rdev_for_each_safe(rdev, tmp, mddev) {
		/*
@@ -1045,7 +1019,6 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
			break;
		default:
			dev = container_of(rdev, struct raid_dev, rdev);
			if (redundancy--) {
			if (dev->meta_dev)
				dm_put_device(ti, dev->meta_dev);

@@ -1072,17 +1045,17 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
			rdev->bdev = NULL;

			list_del(&rdev->same_set);

				continue;
			}
			ti->error = "Failed to load superblock";
			return ret;
		}
	}

	if (!freshest)
		return 0;

	if (validate_raid_redundancy(rs)) {
		rs->ti->error = "Insufficient redundancy to activate array";
		return -EINVAL;
	}

	/*
	 * Validation of the freshest device provides the source of
	 * validation for the remaining devices.
@@ -1432,7 +1405,7 @@ static void raid_resume(struct dm_target *ti)

static struct target_type raid_target = {
	.name = "raid",
	.version = {1, 4, 0},
	.version = {1, 4, 1},
	.module = THIS_MODULE,
	.ctr = raid_ctr,
	.dtr = raid_dtr,