Commit 0447568fc51e0268e201f7086d2450cf986e0411

Authored by Jonathan E Brassow
Committed by Alasdair G Kergon
1 parent fef838cc1a

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,