Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jonathan E Brassow and committed by
Alasdair G Kergon
0447568f fef838cc

+51 -2
+51 -2
drivers/md/dm-raid.c
··· 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 ··· 857 855 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) 858 856 { 859 857 int ret; 858 + unsigned redundancy = 0; 859 + struct raid_dev *dev; 860 860 struct md_rdev *rdev, *freshest; 861 861 struct mddev *mddev = &rs->md; 862 + 863 + switch (rs->raid_type->level) { 864 + case 1: 865 + redundancy = rs->md.raid_disks - 1; 866 + break; 867 + case 4: 868 + case 5: 869 + case 6: 870 + redundancy = rs->raid_type->parity_devs; 871 + break; 872 + default: 873 + ti->error = "Unknown RAID type"; 874 + return -EINVAL; 875 + } 862 876 863 877 freshest = NULL; 864 878 rdev_for_each(rdev, mddev) { ··· 890 872 case 0: 891 873 break; 892 874 default: 875 + dev = container_of(rdev, struct raid_dev, rdev); 876 + if (redundancy--) { 877 + if (dev->meta_dev) 878 + dm_put_device(ti, dev->meta_dev); 879 + 880 + dev->meta_dev = NULL; 881 + rdev->meta_bdev = NULL; 882 + 883 + if (rdev->sb_page) 884 + put_page(rdev->sb_page); 885 + 886 + rdev->sb_page = NULL; 887 + 888 + rdev->sb_loaded = 0; 889 + 890 + /* 891 + * We might be able to salvage the data device 892 + * even though the meta device has failed. For 893 + * now, we behave as though '- -' had been 894 + * set for this device in the table. 895 + */ 896 + if (dev->data_dev) 897 + dm_put_device(ti, dev->data_dev); 898 + 899 + dev->data_dev = NULL; 900 + rdev->bdev = NULL; 901 + 902 + list_del(&rdev->same_set); 903 + 904 + continue; 905 + } 893 906 ti->error = "Failed to load superblock"; 894 907 return ret; 895 908 } ··· 1263 1214 1264 1215 static struct target_type raid_target = { 1265 1216 .name = "raid", 1266 - .version = {1, 1, 0}, 1217 + .version = {1, 2, 0}, 1267 1218 .module = THIS_MODULE, 1268 1219 .ctr = raid_ctr, 1269 1220 .dtr = raid_dtr,