Commit 0447568f authored by Jonathan E Brassow's avatar Jonathan E Brassow Committed by Alasdair G Kergon

dm raid: handle failed devices during start up

The dm-raid code currently fails to create a RAID array if any of the
superblocks cannot be read.  This was an oversight as there is already
code to handle this case if the values ('- -') were provided for the
failed array position.

With this patch, if a superblock cannot be read, the array position's
fields are initialized as though '- -' was set in the table.  That is,
the device is failed and the position should not be used, but if there
is sufficient redundancy, the array should still be activated.
Signed-off-by: default avatarJonathan Brassow <jbrassow@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent fef838cc
...@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size) ...@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
return 0; return 0;
if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) { if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
DMERR("Failed to read device superblock"); DMERR("Failed to read superblock of device at position %d",
rdev->raid_disk);
set_bit(Faulty, &rdev->flags);
return -EINVAL; return -EINVAL;
} }
...@@ -855,9 +857,25 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) ...@@ -855,9 +857,25 @@ 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 md_rdev *rdev, *freshest; struct md_rdev *rdev, *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;
default:
ti->error = "Unknown RAID type";
return -EINVAL;
}
freshest = NULL; freshest = NULL;
rdev_for_each(rdev, mddev) { rdev_for_each(rdev, mddev) {
if (!rdev->meta_bdev) if (!rdev->meta_bdev)
...@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) ...@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
case 0: case 0:
break; break;
default: default:
dev = container_of(rdev, struct raid_dev, rdev);
if (redundancy--) {
if (dev->meta_dev)
dm_put_device(ti, dev->meta_dev);
dev->meta_dev = NULL;
rdev->meta_bdev = NULL;
if (rdev->sb_page)
put_page(rdev->sb_page);
rdev->sb_page = NULL;
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);
dev->data_dev = NULL;
rdev->bdev = NULL;
list_del(&rdev->same_set);
continue;
}
ti->error = "Failed to load superblock"; ti->error = "Failed to load superblock";
return ret; return ret;
} }
...@@ -1214,7 +1263,7 @@ static void raid_resume(struct dm_target *ti) ...@@ -1214,7 +1263,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, 1, 0}, .version = {1, 2, 0},
.module = THIS_MODULE, .module = THIS_MODULE,
.ctr = raid_ctr, .ctr = raid_ctr,
.dtr = raid_dtr, .dtr = raid_dtr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment