Commit 6d508242 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[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: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 61181565
...@@ -906,6 +906,27 @@ static void close_sync(conf_t *conf) ...@@ -906,6 +906,27 @@ static void close_sync(conf_t *conf)
conf->r10buf_pool = NULL; conf->r10buf_pool = NULL;
} }
/* check if there are enough drives for
* every block to appear on atleast one
*/
static int enough(conf_t *conf)
{
int first = 0;
do {
int n = conf->copies;
int cnt = 0;
while (n--) {
if (conf->mirrors[first].rdev)
cnt++;
first = (first+1) % conf->raid_disks;
}
if (cnt == 0)
return 0;
} while (first != 0);
return 1;
}
static int raid10_spare_active(mddev_t *mddev) static int raid10_spare_active(mddev_t *mddev)
{ {
int i; int i;
...@@ -944,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -944,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
* very different from resync * very different from resync
*/ */
return 0; return 0;
if (!enough(conf))
return 0;
for (mirror=0; mirror < mddev->raid_disks; mirror++) for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) { if ( !(p=conf->mirrors+mirror)->rdev) {
...@@ -1684,9 +1707,10 @@ static int run(mddev_t *mddev) ...@@ -1684,9 +1707,10 @@ static int run(mddev_t *mddev)
init_waitqueue_head(&conf->wait_idle); init_waitqueue_head(&conf->wait_idle);
init_waitqueue_head(&conf->wait_resume); init_waitqueue_head(&conf->wait_resume);
if (!conf->working_disks) { /* need to check that every block has at least one working mirror */
printk(KERN_ERR "raid10: no operational mirrors for %s\n", if (!enough(conf)) {
mdname(mddev)); printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
mdname(mddev));
goto out_free_conf; goto out_free_conf;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment