Skip to content

Commit 0447568

Browse files
jbrassowkergon
authored andcommitted
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: Jonathan Brassow <[email protected]> Signed-off-by: Alasdair G Kergon <[email protected]>
1 parent fef838c commit 0447568

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

drivers/md/dm-raid.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
604604
return 0;
605605

606606
if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) {
607-
DMERR("Failed to read device superblock");
607+
DMERR("Failed to read superblock of device at position %d",
608+
rdev->raid_disk);
609+
set_bit(Faulty, &rdev->flags);
608610
return -EINVAL;
609611
}
610612

@@ -855,9 +857,25 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
855857
static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
856858
{
857859
int ret;
860+
unsigned redundancy = 0;
861+
struct raid_dev *dev;
858862
struct md_rdev *rdev, *freshest;
859863
struct mddev *mddev = &rs->md;
860864

865+
switch (rs->raid_type->level) {
866+
case 1:
867+
redundancy = rs->md.raid_disks - 1;
868+
break;
869+
case 4:
870+
case 5:
871+
case 6:
872+
redundancy = rs->raid_type->parity_devs;
873+
break;
874+
default:
875+
ti->error = "Unknown RAID type";
876+
return -EINVAL;
877+
}
878+
861879
freshest = NULL;
862880
rdev_for_each(rdev, mddev) {
863881
if (!rdev->meta_bdev)
@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
872890
case 0:
873891
break;
874892
default:
893+
dev = container_of(rdev, struct raid_dev, rdev);
894+
if (redundancy--) {
895+
if (dev->meta_dev)
896+
dm_put_device(ti, dev->meta_dev);
897+
898+
dev->meta_dev = NULL;
899+
rdev->meta_bdev = NULL;
900+
901+
if (rdev->sb_page)
902+
put_page(rdev->sb_page);
903+
904+
rdev->sb_page = NULL;
905+
906+
rdev->sb_loaded = 0;
907+
908+
/*
909+
* We might be able to salvage the data device
910+
* even though the meta device has failed. For
911+
* now, we behave as though '- -' had been
912+
* set for this device in the table.
913+
*/
914+
if (dev->data_dev)
915+
dm_put_device(ti, dev->data_dev);
916+
917+
dev->data_dev = NULL;
918+
rdev->bdev = NULL;
919+
920+
list_del(&rdev->same_set);
921+
922+
continue;
923+
}
875924
ti->error = "Failed to load superblock";
876925
return ret;
877926
}
@@ -1214,7 +1263,7 @@ static void raid_resume(struct dm_target *ti)
12141263

12151264
static struct target_type raid_target = {
12161265
.name = "raid",
1217-
.version = {1, 1, 0},
1266+
.version = {1, 2, 0},
12181267
.module = THIS_MODULE,
12191268
.ctr = raid_ctr,
12201269
.dtr = raid_dtr,

0 commit comments

Comments
 (0)