aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2005-09-09 19:24:03 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 19:39:14 -0400
commit6d508242b231cb6e6803faaef54456abe846edb8 (patch)
treec41ca18f31dd2320f2ae7b54602682f81bf18e6e
parent611815651b2640449bda928079160b9263efac1c (diff)
[PATCH] md: fix raid10 assembly when too many devices are missing
If you try to assemble an array with too many missing devices, raid10 will now reject the attempt, instead of allowing it. Also check when hot-adding a drive and refuse the hot-add if the array is beyond hope. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/raid10.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 5e0b333793d5..834bf0f86222 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -906,6 +906,27 @@ static void close_sync(conf_t *conf)
906 conf->r10buf_pool = NULL; 906 conf->r10buf_pool = NULL;
907} 907}
908 908
909/* check if there are enough drives for
910 * every block to appear on atleast one
911 */
912static int enough(conf_t *conf)
913{
914 int first = 0;
915
916 do {
917 int n = conf->copies;
918 int cnt = 0;
919 while (n--) {
920 if (conf->mirrors[first].rdev)
921 cnt++;
922 first = (first+1) % conf->raid_disks;
923 }
924 if (cnt == 0)
925 return 0;
926 } while (first != 0);
927 return 1;
928}
929
909static int raid10_spare_active(mddev_t *mddev) 930static int raid10_spare_active(mddev_t *mddev)
910{ 931{
911 int i; 932 int i;
@@ -944,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
944 * very different from resync 965 * very different from resync
945 */ 966 */
946 return 0; 967 return 0;
968 if (!enough(conf))
969 return 0;
947 970
948 for (mirror=0; mirror < mddev->raid_disks; mirror++) 971 for (mirror=0; mirror < mddev->raid_disks; mirror++)
949 if ( !(p=conf->mirrors+mirror)->rdev) { 972 if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -1684,9 +1707,10 @@ static int run(mddev_t *mddev)
1684 init_waitqueue_head(&conf->wait_idle); 1707 init_waitqueue_head(&conf->wait_idle);
1685 init_waitqueue_head(&conf->wait_resume); 1708 init_waitqueue_head(&conf->wait_resume);
1686 1709
1687 if (!conf->working_disks) { 1710 /* need to check that every block has at least one working mirror */
1688 printk(KERN_ERR "raid10: no operational mirrors for %s\n", 1711 if (!enough(conf)) {
1689 mdname(mddev)); 1712 printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
1713 mdname(mddev));
1690 goto out_free_conf; 1714 goto out_free_conf;
1691 } 1715 }
1692 1716