Skip to contentSkip to conversation

Patch "md/raid5: fix a race condition in stripe batch" has been added to the 4.4-stable tree

PATCH [email protected] 1 participant 1 message Oct 2, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

md/raid5: fix a race condition in stripe batch

to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
md-raid5-fix-a-race-condition-in-stripe-batch.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 3664847d95e60a9a943858b7800f8484669740fc Mon Sep 17 00:00:00 2001

From: Shaohua Li <[email protected]>
Date: Fri, 25 Aug 2017 10:40:02 -0700
Subject: md/raid5: fix a race condition in stripe batch

From: Shaohua Li <[email protected]>

commit 3664847d95e60a9a943858b7800f8484669740fc upstream.

We have a race condition in below scenario, say have 3 continuous stripes, sh1, sh2 and sh3, sh1 is the stripe_head of sh2 and sh3:

CPU1 CPU2 CPU3
handle_stripe(sh3)

				stripe_add_to_batch_list(sh3)
				-> lock(sh2, sh3)
				-> lock batch_lock(sh1)
				-> add sh3 to batch_list of sh1
				-> unlock batch_lock(sh1)
								clear_batch_ready(sh1)
								-> lock(sh1) and batch_lock(sh1)
								-> clear STRIPE_BATCH_READY for all stripes in batch_list
								-> unlock(sh1) and batch_lock(sh1)
->clear_batch_ready(sh3)
-->test_and_clear_bit(STRIPE_BATCH_READY, sh3)
--->return 0 as sh->batch == NULL
				-> sh3->batch_head = sh1
				-> unlock (sh2, sh3)

In CPU1, handle_stripe will continue handle sh3 even it's in batch stripe list of sh1. By moving sh3->batch_head assignment in to batch_lock, we make it impossible to clear STRIPE_BATCH_READY before batch_head is set.

Thanks Stephane for helping debug this tricky issue.

---
 drivers/md/raid5.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/md/raid5.c +8 -2
@@ -818,6 +818,14 @@ static void stripe_add_to_batch_list(str
 			spin_unlock(&head->batch_head->batch_lock);
 			goto unlock_out;
 		}
+		/*
+		 * We must assign batch_head of this stripe within the
+		 * batch_lock, otherwise clear_batch_ready of batch head
+		 * stripe could clear BATCH_READY bit of this stripe and
+		 * this stripe->batch_head doesn't get assigned, which
+		 * could confuse clear_batch_ready for this stripe
+		 */
+		sh->batch_head = head->batch_head;
 
 		/*
 		 * at this point, head's BATCH_READY could be cleared, but we
@@ -825,8 +833,6 @@ static void stripe_add_to_batch_list(str
 		 */
 		list_add(&sh->batch_list, &head->batch_list);
 		spin_unlock(&head->batch_head->batch_lock);
-
-		sh->batch_head = head->batch_head;
 	} else {
 		head->batch_head = head;
 		sh->batch_head = head->batch_head;

Patches currently in stable-queue which might be from [email protected] are

queue-4.4/md-raid5-preserve-stripe_on_unplug_list-in-break_stripe_batch_list.patch queue-4.4/md-raid5-fix-a-race-condition-in-stripe-batch.patch