diff options
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 9fd473a6dbf5..6778b7cb39bd 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -773,7 +773,6 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
773 | r1bio_t *r1_bio; | 773 | r1bio_t *r1_bio; |
774 | struct bio *read_bio; | 774 | struct bio *read_bio; |
775 | int i, targets = 0, disks; | 775 | int i, targets = 0, disks; |
776 | mdk_rdev_t *rdev; | ||
777 | struct bitmap *bitmap = mddev->bitmap; | 776 | struct bitmap *bitmap = mddev->bitmap; |
778 | unsigned long flags; | 777 | unsigned long flags; |
779 | struct bio_list bl; | 778 | struct bio_list bl; |
@@ -781,6 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
781 | const int rw = bio_data_dir(bio); | 780 | const int rw = bio_data_dir(bio); |
782 | const int do_sync = bio_sync(bio); | 781 | const int do_sync = bio_sync(bio); |
783 | int do_barriers; | 782 | int do_barriers; |
783 | mdk_rdev_t *blocked_rdev; | ||
784 | 784 | ||
785 | /* | 785 | /* |
786 | * Register the new request and wait if the reconstruction | 786 | * Register the new request and wait if the reconstruction |
@@ -862,10 +862,17 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
862 | first = 0; | 862 | first = 0; |
863 | } | 863 | } |
864 | #endif | 864 | #endif |
865 | retry_write: | ||
866 | blocked_rdev = NULL; | ||
865 | rcu_read_lock(); | 867 | rcu_read_lock(); |
866 | for (i = 0; i < disks; i++) { | 868 | for (i = 0; i < disks; i++) { |
867 | if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL && | 869 | mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); |
868 | !test_bit(Faulty, &rdev->flags)) { | 870 | if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { |
871 | atomic_inc(&rdev->nr_pending); | ||
872 | blocked_rdev = rdev; | ||
873 | break; | ||
874 | } | ||
875 | if (rdev && !test_bit(Faulty, &rdev->flags)) { | ||
869 | atomic_inc(&rdev->nr_pending); | 876 | atomic_inc(&rdev->nr_pending); |
870 | if (test_bit(Faulty, &rdev->flags)) { | 877 | if (test_bit(Faulty, &rdev->flags)) { |
871 | rdev_dec_pending(rdev, mddev); | 878 | rdev_dec_pending(rdev, mddev); |
@@ -878,6 +885,20 @@ static int make_request(struct request_queue *q, struct bio * bio) | |||
878 | } | 885 | } |
879 | rcu_read_unlock(); | 886 | rcu_read_unlock(); |
880 | 887 | ||
888 | if (unlikely(blocked_rdev)) { | ||
889 | /* Wait for this device to become unblocked */ | ||
890 | int j; | ||
891 | |||
892 | for (j = 0; j < i; j++) | ||
893 | if (r1_bio->bios[j]) | ||
894 | rdev_dec_pending(conf->mirrors[j].rdev, mddev); | ||
895 | |||
896 | allow_barrier(conf); | ||
897 | md_wait_for_blocked_rdev(blocked_rdev, mddev); | ||
898 | wait_barrier(conf); | ||
899 | goto retry_write; | ||
900 | } | ||
901 | |||
881 | BUG_ON(targets == 0); /* we never fail the last device */ | 902 | BUG_ON(targets == 0); /* we never fail the last device */ |
882 | 903 | ||
883 | if (targets < conf->raid_disks) { | 904 | if (targets < conf->raid_disks) { |