md/raid5: need_this_block: tidy/fix last condition.
[pandora-kernel.git] / drivers / md / raid5.c
index bb42551..a03cf2d 100644 (file)
@@ -2902,6 +2902,7 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
        struct r5dev *dev = &sh->dev[disk_idx];
        struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
                                  &sh->dev[s->failed_num[1]] };
+       int i;
 
 
        if (test_bit(R5_LOCKED, &dev->flags) ||
@@ -2949,16 +2950,37 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
                 * and there is no need to delay that.
                 */
                return 0;
-       if (
-            (sh->raid_conf->level <= 5 && fdev[0]->towrite &&
-             !test_bit(R5_OVERWRITE, &fdev[0]->flags)) ||
-            ((sh->raid_conf->level == 6 ||
-              sh->sector >= sh->raid_conf->mddev->recovery_cp)
-             &&
-             (s->to_write - s->non_overwrite <
-              sh->raid_conf->raid_disks - sh->raid_conf->max_degraded)
-             ))
-               return 1;
+
+       for (i = 0; i < s->failed; i++) {
+               if (fdev[i]->towrite &&
+                   !test_bit(R5_UPTODATE, &fdev[i]->flags) &&
+                   !test_bit(R5_OVERWRITE, &fdev[i]->flags))
+                       /* If we have a partial write to a failed
+                        * device, then we will need to reconstruct
+                        * the content of that device, so all other
+                        * devices must be read.
+                        */
+                       return 1;
+       }
+
+       /* If we are forced to do a reconstruct-write, either because
+        * the current RAID6 implementation only supports that, or
+        * or because parity cannot be trusted and we are currently
+        * recovering it, there is extra need to be careful.
+        * If one of the devices that we would need to read, because
+        * it is not being overwritten (and maybe not written at all)
+        * is missing/faulty, then we need to read everything we can.
+        */
+       if (sh->raid_conf->level != 6 &&
+           sh->sector < sh->raid_conf->mddev->recovery_cp)
+               /* reconstruct-write isn't being forced */
+               return 0;
+       for (i = 0; i < s->failed; i++) {
+               if (!test_bit(R5_UPTODATE, &fdev[i]->flags) &&
+                   !test_bit(R5_OVERWRITE, &fdev[i]->flags))
+                       return 1;
+       }
+
        return 0;
 }