diff options
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r-- | drivers/md/raid10.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 62ebb1bc72be..5bd1e9ec899d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -538,7 +538,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) | |||
538 | } | 538 | } |
539 | 539 | ||
540 | 540 | ||
541 | current_distance = abs(this_sector - conf->mirrors[disk].head_position); | 541 | current_distance = abs(r10_bio->devs[slot].addr - |
542 | conf->mirrors[disk].head_position); | ||
542 | 543 | ||
543 | /* Find the disk whose head is closest */ | 544 | /* Find the disk whose head is closest */ |
544 | 545 | ||
@@ -668,6 +669,11 @@ static int make_request(request_queue_t *q, struct bio * bio) | |||
668 | int i; | 669 | int i; |
669 | int chunk_sects = conf->chunk_mask + 1; | 670 | int chunk_sects = conf->chunk_mask + 1; |
670 | 671 | ||
672 | if (unlikely(bio_barrier(bio))) { | ||
673 | bio_endio(bio, bio->bi_size, -EOPNOTSUPP); | ||
674 | return 0; | ||
675 | } | ||
676 | |||
671 | /* If this request crosses a chunk boundary, we need to | 677 | /* If this request crosses a chunk boundary, we need to |
672 | * split it. This will only happen for 1 PAGE (or less) requests. | 678 | * split it. This will only happen for 1 PAGE (or less) requests. |
673 | */ | 679 | */ |
@@ -900,6 +906,27 @@ static void close_sync(conf_t *conf) | |||
900 | conf->r10buf_pool = NULL; | 906 | conf->r10buf_pool = NULL; |
901 | } | 907 | } |
902 | 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 | |||
903 | static int raid10_spare_active(mddev_t *mddev) | 930 | static int raid10_spare_active(mddev_t *mddev) |
904 | { | 931 | { |
905 | int i; | 932 | int i; |
@@ -938,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
938 | * very different from resync | 965 | * very different from resync |
939 | */ | 966 | */ |
940 | return 0; | 967 | return 0; |
968 | if (!enough(conf)) | ||
969 | return 0; | ||
941 | 970 | ||
942 | for (mirror=0; mirror < mddev->raid_disks; mirror++) | 971 | for (mirror=0; mirror < mddev->raid_disks; mirror++) |
943 | if ( !(p=conf->mirrors+mirror)->rdev) { | 972 | if ( !(p=conf->mirrors+mirror)->rdev) { |
@@ -1445,7 +1474,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1445 | } | 1474 | } |
1446 | } | 1475 | } |
1447 | if (j == conf->copies) { | 1476 | if (j == conf->copies) { |
1448 | BUG(); | 1477 | /* Cannot recover, so abort the recovery */ |
1478 | put_buf(r10_bio); | ||
1479 | r10_bio = rb2; | ||
1480 | if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery)) | ||
1481 | printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n", | ||
1482 | mdname(mddev)); | ||
1483 | break; | ||
1449 | } | 1484 | } |
1450 | } | 1485 | } |
1451 | if (biolist == NULL) { | 1486 | if (biolist == NULL) { |
@@ -1678,9 +1713,10 @@ static int run(mddev_t *mddev) | |||
1678 | init_waitqueue_head(&conf->wait_idle); | 1713 | init_waitqueue_head(&conf->wait_idle); |
1679 | init_waitqueue_head(&conf->wait_resume); | 1714 | init_waitqueue_head(&conf->wait_resume); |
1680 | 1715 | ||
1681 | if (!conf->working_disks) { | 1716 | /* need to check that every block has at least one working mirror */ |
1682 | printk(KERN_ERR "raid10: no operational mirrors for %s\n", | 1717 | if (!enough(conf)) { |
1683 | mdname(mddev)); | 1718 | printk(KERN_ERR "raid10: not enough operational mirrors for %s\n", |
1719 | mdname(mddev)); | ||
1684 | goto out_free_conf; | 1720 | goto out_free_conf; |
1685 | } | 1721 | } |
1686 | 1722 | ||