Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 349322
b: refs/heads/master
c: 41d82bd
h: refs/heads/master
v: v3
  • Loading branch information
Li Zhong authored and Benjamin Herrenschmidt committed Jan 28, 2013
1 parent 8b4ce67 commit 070ca3a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f94d4fe0b5bbe8385245a1d9ef11d785c05df0da
refs/heads/master: 41d82bdb40af74a88cff4589ea7a60091b11070e
1 change: 0 additions & 1 deletion trunk/Documentation/device-mapper/dm-raid.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,3 @@ 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
2 changes: 2 additions & 0 deletions trunk/arch/powerpc/kernel/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ ret_from_fork:
ret_from_kernel_thread:
REST_NVGPRS(r1)
bl schedule_tail
li r3,0
stw r3,0(r1)
mtlr r14
mr r3,r15
PPC440EP_ERR42
Expand Down
101 changes: 64 additions & 37 deletions trunk/drivers/md/dm-raid.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,22 +340,24 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
}

/*
* validate_raid_redundancy
* validate_rebuild_devices
* @rs
*
* Determine if there are enough devices in the array that haven't
* failed (or are being rebuilt) to form a usable array.
* Determine if the devices specified for rebuild can result in a valid
* usable array that is capable of rebuilding the given devices.
*
* Returns: 0 on success, -EINVAL on failure.
*/
static int validate_raid_redundancy(struct raid_set *rs)
static int validate_rebuild_devices(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) ||
!rs->dev[i].rdev.sb_page)
if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
rebuild_cnt++;

switch (rs->raid_type->level) {
Expand Down Expand Up @@ -391,24 +393,27 @@ static int validate_raid_redundancy(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 ((!rs->dev[d].rdev.sb_page ||
!test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
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:
if (rebuild_cnt)
return -EINVAL;
DMERR("The rebuild parameter is not supported for %s",
rs->raid_type->name);
rs->ti->error = "Rebuild not supported for this RAID type";
return -EINVAL;
}

return 0;

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

Expand Down Expand Up @@ -659,6 +664,9 @@ 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;
Expand Down Expand Up @@ -987,10 +995,28 @@ 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) {
/*
Expand Down Expand Up @@ -1019,43 +1045,44 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
break;
default:
dev = container_of(rdev, struct raid_dev, rdev);
if (dev->meta_dev)
dm_put_device(ti, dev->meta_dev);
if (redundancy--) {
if (dev->meta_dev)
dm_put_device(ti, dev->meta_dev);

dev->meta_dev = NULL;
rdev->meta_bdev = NULL;
dev->meta_dev = NULL;
rdev->meta_bdev = NULL;

if (rdev->sb_page)
put_page(rdev->sb_page);
if (rdev->sb_page)
put_page(rdev->sb_page);

rdev->sb_page = NULL;
rdev->sb_page = NULL;

rdev->sb_loaded = 0;
rdev->sb_loaded = 0;

/*
* We might be able to salvage the data device
* even though the meta device has failed. For
* now, we behave as though '- -' had been
* set for this device in the table.
*/
if (dev->data_dev)
dm_put_device(ti, dev->data_dev);
/*
* We might be able to salvage the data device
* even though the meta device has failed. For
* now, we behave as though '- -' had been
* set for this device in the table.
*/
if (dev->data_dev)
dm_put_device(ti, dev->data_dev);

dev->data_dev = NULL;
rdev->bdev = NULL;

dev->data_dev = NULL;
rdev->bdev = NULL;
list_del(&rdev->same_set);

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.
Expand Down Expand Up @@ -1405,7 +1432,7 @@ static void raid_resume(struct dm_target *ti)

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

0 comments on commit 070ca3a

Please sign in to comment.