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

Commit 4ec1e369 authored by Jonathan Brassow's avatar Jonathan Brassow Committed by NeilBrown
Browse files

DM RAID: Add rebuild capability for RAID10



DM RAID:  Add code to validate replacement slots for RAID10 arrays

RAID10 can handle 'copies - 1' failures for each mirror group.  This code
ensures the user has provided a valid array - one whose devices specified for
rebuild do not exceed the amount of redundancy available.

Signed-off-by: default avatarJonathan Brassow <jbrassow@redhat.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent eb649123
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -132,3 +132,12 @@ Here we can see the RAID type is raid4, there are 5 devices - all of
which are 'A'live, and the array is 2/490221568 complete with recovery.
which are 'A'live, and the array is 2/490221568 complete with recovery.
Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
are marked 'a'.
are marked 'a'.


Version History
---------------
1.0.0	Initial version.  Support for RAID 4/5/6
1.1.0	Added support for RAID 1
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
+33 −1
Original line number Original line Diff line number Diff line
@@ -349,6 +349,7 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
static int validate_rebuild_devices(struct raid_set *rs)
static int validate_rebuild_devices(struct raid_set *rs)
{
{
	unsigned i, rebuild_cnt = 0;
	unsigned i, rebuild_cnt = 0;
	unsigned rebuilds_per_group, copies, d;


	if (!(rs->print_flags & DMPF_REBUILD))
	if (!(rs->print_flags & DMPF_REBUILD))
		return 0;
		return 0;
@@ -369,6 +370,37 @@ static int validate_rebuild_devices(struct raid_set *rs)
			goto too_many;
			goto too_many;
		break;
		break;
	case 10:
	case 10:
		copies = raid10_md_layout_to_copies(rs->md.layout);
		if (rebuild_cnt < copies)
			break;

		/*
		 * It is possible to have a higher rebuild count for RAID10,
		 * as long as the failed devices occur in different mirror
		 * groups (i.e. different stripes).
		 *
		 * Right now, we only allow for "near" copies.  When other
		 * formats are added, we will have to check those too.
		 *
		 * When checking "near" format, make sure no adjacent devices
		 * have failed beyond what can be handled.  In addition to the
		 * simple case where the number of devices is a multiple of the
		 * number of copies, we must also handle cases where the number
		 * of devices is not a multiple of the number of copies.
		 * E.g.    dev1 dev2 dev3 dev4 dev5
		 *          A    A    B    B    C
		 *          C    D    D    E    E
		 */
		rebuilds_per_group = 0;
		for (i = 0; i < rs->md.raid_disks * copies; i++) {
			d = i % rs->md.raid_disks;
			if (!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:
	default:
		DMERR("The rebuild parameter is not supported for %s",
		DMERR("The rebuild parameter is not supported for %s",
		      rs->raid_type->name);
		      rs->raid_type->name);
@@ -1385,7 +1417,7 @@ static void raid_resume(struct dm_target *ti)


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