diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 472aedfb07cf..31670f8d6b65 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3036,6 +3036,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3036 | if (dev->written) | 3036 | if (dev->written) |
3037 | s->written++; | 3037 | s->written++; |
3038 | rdev = rcu_dereference(conf->disks[i].rdev); | 3038 | rdev = rcu_dereference(conf->disks[i].rdev); |
3039 | if (rdev && test_bit(Faulty, &rdev->flags)) | ||
3040 | rdev = NULL; | ||
3039 | if (rdev) { | 3041 | if (rdev) { |
3040 | is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS, | 3042 | is_bad = is_badblock(rdev, sh->sector, STRIPE_SECTORS, |
3041 | &first_bad, &bad_sectors); | 3043 | &first_bad, &bad_sectors); |
@@ -3063,12 +3065,12 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3063 | } | 3065 | } |
3064 | } else if (test_bit(In_sync, &rdev->flags)) | 3066 | } else if (test_bit(In_sync, &rdev->flags)) |
3065 | set_bit(R5_Insync, &dev->flags); | 3067 | set_bit(R5_Insync, &dev->flags); |
3066 | else if (!test_bit(Faulty, &rdev->flags)) { | 3068 | else { |
3067 | /* in sync if before recovery_offset */ | 3069 | /* in sync if before recovery_offset */ |
3068 | if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) | 3070 | if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) |
3069 | set_bit(R5_Insync, &dev->flags); | 3071 | set_bit(R5_Insync, &dev->flags); |
3070 | } | 3072 | } |
3071 | if (test_bit(R5_WriteError, &dev->flags)) { | 3073 | if (rdev && test_bit(R5_WriteError, &dev->flags)) { |
3072 | clear_bit(R5_Insync, &dev->flags); | 3074 | clear_bit(R5_Insync, &dev->flags); |
3073 | if (!test_bit(Faulty, &rdev->flags)) { | 3075 | if (!test_bit(Faulty, &rdev->flags)) { |
3074 | s->handle_bad_blocks = 1; | 3076 | s->handle_bad_blocks = 1; |
@@ -3076,7 +3078,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3076 | } else | 3078 | } else |
3077 | clear_bit(R5_WriteError, &dev->flags); | 3079 | clear_bit(R5_WriteError, &dev->flags); |
3078 | } | 3080 | } |
3079 | if (test_bit(R5_MadeGood, &dev->flags)) { | 3081 | if (rdev && test_bit(R5_MadeGood, &dev->flags)) { |
3080 | if (!test_bit(Faulty, &rdev->flags)) { | 3082 | if (!test_bit(Faulty, &rdev->flags)) { |
3081 | s->handle_bad_blocks = 1; | 3083 | s->handle_bad_blocks = 1; |
3082 | atomic_inc(&rdev->nr_pending); | 3084 | atomic_inc(&rdev->nr_pending); |
@@ -3110,7 +3112,7 @@ static void handle_stripe(struct stripe_head *sh) | |||
3110 | struct r5dev *pdev, *qdev; | 3112 | struct r5dev *pdev, *qdev; |
3111 | 3113 | ||
3112 | clear_bit(STRIPE_HANDLE, &sh->state); | 3114 | clear_bit(STRIPE_HANDLE, &sh->state); |
3113 | if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) { | 3115 | if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) { |
3114 | /* already being handled, ensure it gets handled | 3116 | /* already being handled, ensure it gets handled |
3115 | * again when current action finishes */ | 3117 | * again when current action finishes */ |
3116 | set_bit(STRIPE_HANDLE, &sh->state); | 3118 | set_bit(STRIPE_HANDLE, &sh->state); |
@@ -3159,10 +3161,14 @@ static void handle_stripe(struct stripe_head *sh) | |||
3159 | /* check if the array has lost more than max_degraded devices and, | 3161 | /* check if the array has lost more than max_degraded devices and, |
3160 | * if so, some requests might need to be failed. | 3162 | * if so, some requests might need to be failed. |
3161 | */ | 3163 | */ |
3162 | if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written) | 3164 | if (s.failed > conf->max_degraded) { |
3163 | handle_failed_stripe(conf, sh, &s, disks, &s.return_bi); | 3165 | sh->check_state = 0; |
3164 | if (s.failed > conf->max_degraded && s.syncing) | 3166 | sh->reconstruct_state = 0; |
3165 | handle_failed_sync(conf, sh, &s); | 3167 | if (s.to_read+s.to_write+s.written) |
3168 | handle_failed_stripe(conf, sh, &s, disks, &s.return_bi); | ||
3169 | if (s.syncing) | ||
3170 | handle_failed_sync(conf, sh, &s); | ||
3171 | } | ||
3166 | 3172 | ||
3167 | /* | 3173 | /* |
3168 | * might be able to return some write requests if the parity blocks | 3174 | * might be able to return some write requests if the parity blocks |
@@ -3371,7 +3377,7 @@ finish: | |||
3371 | 3377 | ||
3372 | return_io(s.return_bi); | 3378 | return_io(s.return_bi); |
3373 | 3379 | ||
3374 | clear_bit(STRIPE_ACTIVE, &sh->state); | 3380 | clear_bit_unlock(STRIPE_ACTIVE, &sh->state); |
3375 | } | 3381 | } |
3376 | 3382 | ||
3377 | static void raid5_activate_delayed(struct r5conf *conf) | 3383 | static void raid5_activate_delayed(struct r5conf *conf) |