@@ -2806,12 +2806,25 @@ static void handle_stripe_dirtying(struct r5conf *conf,
28062806 int disks )
28072807{
28082808 int rmw = 0 , rcw = 0 , i ;
2809- if (conf -> max_degraded == 2 ) {
2810- /* RAID6 requires 'rcw' in current implementation
2811- * Calculate the real rcw later - for now fake it
2809+ sector_t recovery_cp = conf -> mddev -> recovery_cp ;
2810+
2811+ /* RAID6 requires 'rcw' in current implementation.
2812+ * Otherwise, check whether resync is now happening or should start.
2813+ * If yes, then the array is dirty (after unclean shutdown or
2814+ * initial creation), so parity in some stripes might be inconsistent.
2815+ * In this case, we need to always do reconstruct-write, to ensure
2816+ * that in case of drive failure or read-error correction, we
2817+ * generate correct data from the parity.
2818+ */
2819+ if (conf -> max_degraded == 2 ||
2820+ (recovery_cp < MaxSector && sh -> sector >= recovery_cp )) {
2821+ /* Calculate the real rcw later - for now make it
28122822 * look like rcw is cheaper
28132823 */
28142824 rcw = 1 ; rmw = 2 ;
2825+ pr_debug ("force RCW max_degraded=%u, recovery_cp=%llu sh->sector=%llu\n" ,
2826+ conf -> max_degraded , (unsigned long long )recovery_cp ,
2827+ (unsigned long long )sh -> sector );
28152828 } else for (i = disks ; i -- ; ) {
28162829 /* would I have to read this buffer for read_modify_write */
28172830 struct r5dev * dev = & sh -> dev [i ];
0 commit comments