diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 17e0953c3c0..224de022e7c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2568,10 +2568,10 @@ static bool handle_stripe5(struct stripe_head *sh) | |||
2568 | if (dev->written) | 2568 | if (dev->written) |
2569 | s.written++; | 2569 | s.written++; |
2570 | rdev = rcu_dereference(conf->disks[i].rdev); | 2570 | rdev = rcu_dereference(conf->disks[i].rdev); |
2571 | if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | 2571 | if (blocked_rdev == NULL && |
2572 | rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | ||
2572 | blocked_rdev = rdev; | 2573 | blocked_rdev = rdev; |
2573 | atomic_inc(&rdev->nr_pending); | 2574 | atomic_inc(&rdev->nr_pending); |
2574 | break; | ||
2575 | } | 2575 | } |
2576 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 2576 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { |
2577 | /* The ReadError flag will just be confusing now */ | 2577 | /* The ReadError flag will just be confusing now */ |
@@ -2588,8 +2588,14 @@ static bool handle_stripe5(struct stripe_head *sh) | |||
2588 | rcu_read_unlock(); | 2588 | rcu_read_unlock(); |
2589 | 2589 | ||
2590 | if (unlikely(blocked_rdev)) { | 2590 | if (unlikely(blocked_rdev)) { |
2591 | set_bit(STRIPE_HANDLE, &sh->state); | 2591 | if (s.syncing || s.expanding || s.expanded || |
2592 | goto unlock; | 2592 | s.to_write || s.written) { |
2593 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2594 | goto unlock; | ||
2595 | } | ||
2596 | /* There is nothing for the blocked_rdev to block */ | ||
2597 | rdev_dec_pending(blocked_rdev, conf->mddev); | ||
2598 | blocked_rdev = NULL; | ||
2593 | } | 2599 | } |
2594 | 2600 | ||
2595 | if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { | 2601 | if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { |
@@ -2832,10 +2838,10 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2832 | if (dev->written) | 2838 | if (dev->written) |
2833 | s.written++; | 2839 | s.written++; |
2834 | rdev = rcu_dereference(conf->disks[i].rdev); | 2840 | rdev = rcu_dereference(conf->disks[i].rdev); |
2835 | if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | 2841 | if (blocked_rdev == NULL && |
2842 | rdev && unlikely(test_bit(Blocked, &rdev->flags))) { | ||
2836 | blocked_rdev = rdev; | 2843 | blocked_rdev = rdev; |
2837 | atomic_inc(&rdev->nr_pending); | 2844 | atomic_inc(&rdev->nr_pending); |
2838 | break; | ||
2839 | } | 2845 | } |
2840 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 2846 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { |
2841 | /* The ReadError flag will just be confusing now */ | 2847 | /* The ReadError flag will just be confusing now */ |
@@ -2853,9 +2859,16 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2853 | rcu_read_unlock(); | 2859 | rcu_read_unlock(); |
2854 | 2860 | ||
2855 | if (unlikely(blocked_rdev)) { | 2861 | if (unlikely(blocked_rdev)) { |
2856 | set_bit(STRIPE_HANDLE, &sh->state); | 2862 | if (s.syncing || s.expanding || s.expanded || |
2857 | goto unlock; | 2863 | s.to_write || s.written) { |
2864 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2865 | goto unlock; | ||
2866 | } | ||
2867 | /* There is nothing for the blocked_rdev to block */ | ||
2868 | rdev_dec_pending(blocked_rdev, conf->mddev); | ||
2869 | blocked_rdev = NULL; | ||
2858 | } | 2870 | } |
2871 | |||
2859 | pr_debug("locked=%d uptodate=%d to_read=%d" | 2872 | pr_debug("locked=%d uptodate=%d to_read=%d" |
2860 | " to_write=%d failed=%d failed_num=%d,%d\n", | 2873 | " to_write=%d failed=%d failed_num=%d,%d\n", |
2861 | s.locked, s.uptodate, s.to_read, s.to_write, s.failed, | 2874 | s.locked, s.uptodate, s.to_read, s.to_write, s.failed, |