aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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