aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r--drivers/md/raid10.c46
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 */
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
903static int raid10_spare_active(mddev_t *mddev) 930static 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