md: close a livelock window in handle_parity_checks5

If a failure is detected after a parity check operation has been initiated,
but before it completes handle_parity_checks5 will never quiesce operations on
the stripe.

Explicitly handle this case by "canceling" the parity check, i.e. clear the
STRIPE_OP_CHECK flags and queue the stripe on the handle list again to refresh
any non-uptodate blocks.

Kernel versions >= 2.6.23 are susceptible.

Cc: <stable@kernel.org>
Cc: NeilBrown <neilb@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Dan Williams and committed by Linus Torvalds bd2ab670 231bc2a2

+31 -24
+31 -24
drivers/md/raid5.c
··· 2348 2348 static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, 2349 2349 struct stripe_head_state *s, int disks) 2350 2350 { 2351 - set_bit(STRIPE_HANDLE, &sh->state); 2352 - /* Take one of the following actions: 2353 - * 1/ start a check parity operation if (uptodate == disks) 2354 - * 2/ finish a check parity operation and act on the result 2355 - * 3/ skip to the writeback section if we previously 2356 - * initiated a recovery operation 2357 - */ 2358 - if (s->failed == 0 && 2359 - !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { 2360 - if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) { 2361 - BUG_ON(s->uptodate != disks); 2362 - clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); 2363 - sh->ops.count++; 2364 - s->uptodate--; 2365 - } else if ( 2366 - test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) { 2367 - clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); 2368 - clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); 2351 + int canceled_check = 0; 2369 2352 2353 + set_bit(STRIPE_HANDLE, &sh->state); 2354 + 2355 + /* complete a check operation */ 2356 + if (test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) { 2357 + clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); 2358 + clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); 2359 + if (s->failed == 0) { 2370 2360 if (sh->ops.zero_sum_result == 0) 2371 2361 /* parity is correct (on disc, 2372 2362 * not in buffer any more) ··· 2381 2391 s->uptodate++; 2382 2392 } 2383 2393 } 2384 - } 2394 + } else 2395 + canceled_check = 1; /* STRIPE_INSYNC is not set */ 2385 2396 } 2386 2397 2387 2398 /* check if we can clear a parity disk reconstruct */ ··· 2395 2404 clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); 2396 2405 } 2397 2406 2398 - /* Wait for check parity and compute block operations to complete 2399 - * before write-back 2407 + /* start a new check operation if there are no failures, the stripe is 2408 + * not insync, and a repair is not in flight 2400 2409 */ 2401 - if (!test_bit(STRIPE_INSYNC, &sh->state) && 2402 - !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) && 2403 - !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) { 2410 + if (s->failed == 0 && 2411 + !test_bit(STRIPE_INSYNC, &sh->state) && 2412 + !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { 2413 + if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) { 2414 + BUG_ON(s->uptodate != disks); 2415 + clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); 2416 + sh->ops.count++; 2417 + s->uptodate--; 2418 + } 2419 + } 2420 + 2421 + /* Wait for check parity and compute block operations to complete 2422 + * before write-back. If a failure occurred while the check operation 2423 + * was in flight we need to cycle this stripe through handle_stripe 2424 + * since the parity block may not be uptodate 2425 + */ 2426 + if (!canceled_check && !test_bit(STRIPE_INSYNC, &sh->state) && 2427 + !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) && 2428 + !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) { 2404 2429 struct r5dev *dev; 2405 2430 /* either failed parity check, or recovery is happening */ 2406 2431 if (s->failed == 0)