aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJonathan E Brassow <jbrassow@redhat.com>2012-03-28 13:41:26 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-03-28 13:41:26 -0400
commit0447568fc51e0268e201f7086d2450cf986e0411 (patch)
tree879a6e4ae0b156f05487ac2eb058920e83a0285e /drivers/md
parentfef838cc1ac34e599c74888274506d76767f3098 (diff)
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 <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-raid.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index c5a875d7b882..b0ba52459ed7 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -604,7 +604,9 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
604 return 0; 604 return 0;
605 605
606 if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) { 606 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);
608 return -EINVAL; 610 return -EINVAL;
609 } 611 }
610 612
@@ -855,9 +857,25 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev)
855static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) 857static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
856{ 858{
857 int ret; 859 int ret;
860 unsigned redundancy = 0;
861 struct raid_dev *dev;
858 struct md_rdev *rdev, *freshest; 862 struct md_rdev *rdev, *freshest;
859 struct mddev *mddev = &rs->md; 863 struct mddev *mddev = &rs->md;
860 864
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
861 freshest = NULL; 879 freshest = NULL;
862 rdev_for_each(rdev, mddev) { 880 rdev_for_each(rdev, mddev) {
863 if (!rdev->meta_bdev) 881 if (!rdev->meta_bdev)
@@ -872,6 +890,37 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
872 case 0: 890 case 0:
873 break; 891 break;
874 default: 892 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 }
875 ti->error = "Failed to load superblock"; 924 ti->error = "Failed to load superblock";
876 return ret; 925 return ret;
877 } 926 }
@@ -1214,7 +1263,7 @@ static void raid_resume(struct dm_target *ti)
1214 1263
1215static struct target_type raid_target = { 1264static struct target_type raid_target = {
1216 .name = "raid", 1265 .name = "raid",
1217 .version = {1, 1, 0}, 1266 .version = {1, 2, 0},
1218 .module = THIS_MODULE, 1267 .module = THIS_MODULE,
1219 .ctr = raid_ctr, 1268 .ctr = raid_ctr,
1220 .dtr = raid_dtr, 1269 .dtr = raid_dtr,