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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIVAwUAUQb0OTnsnt1WYoG5AQJ4qg/8DIs0eWaJWF5lqF8qJBeMQrUDkqe7glqe
 ezwVlO48uxVzJUxCMd1aZdxjTI/AIvqZ1U5DBC62SlB/RqWlrwIQIIok5odWfnG4
 eAII5hUnktWqL4Ksqz4mgdI+WWwSc3JR7verqS4wOvcsN4qU5t8vL6dj2b0cNYCQ
 I7B+fkMZE1KE4Y2DOf8dEO9gbNIO1ZllZapLRolrsGOr8Ggo1prEoMxBYF5HZNoE
 J1As2N6NA7/kadtsfkCSs+f//5t1uMZluMjEUe4lDmgeqzqz/93kFmJ2OfSdqO4J
 wuuTHbCL+NSjjAZuByluSO98O0h87xXGVMv/c7gadVQtOn6I1DA2i4wTaiHOzr4K
 cdALvbteVCAPYLMA+s8ee6YYbB5pnlblT8FShG+3O6ae1KmbqKex1LlZLpwEoS8y
 VxI1WCSQbBr/ejAnhxLFQPo5OAcoeHomlZHKPtCBSbwQ0f0pOHHPYlZyX2PtX6hF
 U9bmtMq0XZulDORdLmIsEEpwzRKQ+b89+RrYXM7AhkJTxRP59RVwqFHy9SybcFBS
 S5XFKqpCE+ioBvLp9HK189xMe0Nel2g7KWd34v5LcvQ21rzATezAh5TsWIzN3oV8
 9/phd6nZa0hhcELykOTmK5b6+ks2tBfEN2FuyKfSq4Z2nz46rfD4wYVTY2+Qjh+D
 hmUDBgguejo=
 =bJyL
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2013-01-28 15:15:34 -08:00
commit f94d4fe0b5
2 changed files with 38 additions and 64 deletions

View File

@ -141,3 +141,4 @@ Version History
1.2.0 Handle creation of arrays that contain failed devices. 1.2.0 Handle creation of arrays that contain failed devices.
1.3.0 Added support for RAID 10 1.3.0 Added support for RAID 10
1.3.1 Allow device replacement/rebuild for RAID 10 1.3.1 Allow device replacement/rebuild for RAID 10
1.3.2 Fix/improve redundancy checking for RAID10

View File

@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
} }
/* /*
* validate_rebuild_devices * validate_raid_redundancy
* @rs * @rs
* *
* Determine if the devices specified for rebuild can result in a valid * Determine if there are enough devices in the array that haven't
* usable array that is capable of rebuilding the given devices. * failed (or are being rebuilt) to form a usable array.
* *
* Returns: 0 on success, -EINVAL on failure. * 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 i, rebuild_cnt = 0;
unsigned rebuilds_per_group, copies, d; unsigned rebuilds_per_group, copies, d;
if (!(rs->print_flags & DMPF_REBUILD))
return 0;
for (i = 0; i < rs->md.raid_disks; i++) 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++; rebuild_cnt++;
switch (rs->raid_type->level) { switch (rs->raid_type->level) {
@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs)
* A A B B C * A A B B C
* C D D E E * C D D E E
*/ */
rebuilds_per_group = 0;
for (i = 0; i < rs->md.raid_disks * copies; i++) { for (i = 0; i < rs->md.raid_disks * copies; i++) {
if (!(i % copies))
rebuilds_per_group = 0;
d = i % rs->md.raid_disks; 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)) (++rebuilds_per_group >= copies))
goto too_many; goto too_many;
if (!((i + 1) % copies))
rebuilds_per_group = 0;
} }
break; break;
default: default:
DMERR("The rebuild parameter is not supported for %s", if (rebuild_cnt)
rs->raid_type->name); return -EINVAL;
rs->ti->error = "Rebuild not supported for this RAID type";
return -EINVAL;
} }
return 0; return 0;
too_many: too_many:
rs->ti->error = "Too many rebuild devices specified";
return -EINVAL; return -EINVAL;
} }
@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
} }
rs->md.dev_sectors = sectors_per_dev; 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 */ /* Assume there are no metadata devices until the drives are parsed */
rs->md.persistent = 0; rs->md.persistent = 0;
rs->md.external = 1; 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) static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
{ {
int ret; int ret;
unsigned redundancy = 0;
struct raid_dev *dev; struct raid_dev *dev;
struct md_rdev *rdev, *tmp, *freshest; struct md_rdev *rdev, *tmp, *freshest;
struct mddev *mddev = &rs->md; 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; freshest = NULL;
rdev_for_each_safe(rdev, tmp, mddev) { rdev_for_each_safe(rdev, tmp, mddev) {
/* /*
@ -1045,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
break; break;
default: default:
dev = container_of(rdev, struct raid_dev, rdev); dev = container_of(rdev, struct raid_dev, rdev);
if (redundancy--) { if (dev->meta_dev)
if (dev->meta_dev) dm_put_device(ti, dev->meta_dev);
dm_put_device(ti, dev->meta_dev);
dev->meta_dev = NULL; dev->meta_dev = NULL;
rdev->meta_bdev = NULL; rdev->meta_bdev = NULL;
if (rdev->sb_page) if (rdev->sb_page)
put_page(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 * We might be able to salvage the data device
* even though the meta device has failed. For * even though the meta device has failed. For
* now, we behave as though '- -' had been * now, we behave as though '- -' had been
* set for this device in the table. * set for this device in the table.
*/ */
if (dev->data_dev) if (dev->data_dev)
dm_put_device(ti, dev->data_dev); dm_put_device(ti, dev->data_dev);
dev->data_dev = NULL; dev->data_dev = NULL;
rdev->bdev = 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) if (!freshest)
return 0; 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 of the freshest device provides the source of
* validation for the remaining devices. * validation for the remaining devices.
@ -1432,7 +1405,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, 4, 0}, .version = {1, 4, 1},
.module = THIS_MODULE, .module = THIS_MODULE,
.ctr = raid_ctr, .ctr = raid_ctr,
.dtr = raid_dtr, .dtr = raid_dtr,