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 | ||
