Commit 0447568fc51e0268e201f7086d2450cf986e0411
Committed by
Alasdair G Kergon
1 parent
fef838cc1a
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 51 additions and 2 deletions Side-by-side Diff
drivers/md/dm-raid.c
... | ... | @@ -604,7 +604,9 @@ |
604 | 604 | return 0; |
605 | 605 | |
606 | 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 | 610 | return -EINVAL; |
609 | 611 | } |
610 | 612 | |
611 | 613 | |
... | ... | @@ -855,9 +857,25 @@ |
855 | 857 | static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) |
856 | 858 | { |
857 | 859 | int ret; |
860 | + unsigned redundancy = 0; | |
861 | + struct raid_dev *dev; | |
858 | 862 | struct md_rdev *rdev, *freshest; |
859 | 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 | 879 | freshest = NULL; |
862 | 880 | rdev_for_each(rdev, mddev) { |
863 | 881 | if (!rdev->meta_bdev) |
... | ... | @@ -872,6 +890,37 @@ |
872 | 890 | case 0: |
873 | 891 | break; |
874 | 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 | 924 | ti->error = "Failed to load superblock"; |
876 | 925 | return ret; |
877 | 926 | } |
... | ... | @@ -1214,7 +1263,7 @@ |
1214 | 1263 | |
1215 | 1264 | static struct target_type raid_target = { |
1216 | 1265 | .name = "raid", |
1217 | - .version = {1, 1, 0}, | |
1266 | + .version = {1, 2, 0}, | |
1218 | 1267 | .module = THIS_MODULE, |
1219 | 1268 | .ctr = raid_ctr, |
1220 | 1269 | .dtr = raid_dtr, |