aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-05-22 15:20:04 +1000
committerNeilBrown <neilb@suse.de>2015-05-28 11:35:47 +1000
commitb15a9dbdbfe72848b7ed4cd3f97fe80daaf99c89 (patch)
tree6ded7e7742996dea5e05f46802b2cb800fbfa49d /drivers/md
parentmd/raid5: close race between STRIPE_BIT_DELAY and batching. (diff)
downloadlinux-dev-b15a9dbdbfe72848b7ed4cd3f97fe80daaf99c89.tar.xz
linux-dev-b15a9dbdbfe72848b7ed4cd3f97fe80daaf99c89.zip
md/raid5: Ensure a batch member is not handled prematurely.
If a stripe is a member of a batch, but not the head, it must not be handled separately from the rest of the batch. 'clear_batch_ready()' handles this requirement to some extent but not completely. If a member is passed to handle_stripe() a second time it returns '0' indicating the stripe can be handled, which is wrong. So add an extra test. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid5.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 42d0ea6c8597..e58736740bac 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4200,9 +4200,13 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
static int clear_batch_ready(struct stripe_head *sh)
{
+ /* Return '1' if this is a member of batch, or
+ * '0' if it is a lone stripe or a head which can now be
+ * handled.
+ */
struct stripe_head *tmp;
if (!test_and_clear_bit(STRIPE_BATCH_READY, &sh->state))
- return 0;
+ return (sh->batch_head && sh->batch_head != sh);
spin_lock(&sh->stripe_lock);
if (!sh->batch_head) {
spin_unlock(&sh->stripe_lock);