diff options
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r-- | drivers/md/raid10.c | 30 |
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 | */ | ||
912 | static 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 | |||
909 | static int raid10_spare_active(mddev_t *mddev) | 930 | static 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 | ||