Commit c9445555 authored by Shaohua Li's avatar Shaohua Li

raid5: fix a small race condition

commit 5f9d1fde(raid5: fix memory leak of bio integrity data)
moves bio_reset to bio_endio. But it introduces a small race condition.
It does bio_reset after raid5_release_stripe, which could make the
stripe reusable and hence reuse the bio just before bio_reset. Moving
bio_reset before raid5_release_stripe is called should fix the race.
Reported-and-tested-by: default avatarStefan Priebe - Profihost AG <s.priebe@profihost.ag>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent 47a7b0d8
...@@ -2423,10 +2423,10 @@ static void raid5_end_read_request(struct bio * bi) ...@@ -2423,10 +2423,10 @@ static void raid5_end_read_request(struct bio * bi)
} }
} }
rdev_dec_pending(rdev, conf->mddev); rdev_dec_pending(rdev, conf->mddev);
bio_reset(bi);
clear_bit(R5_LOCKED, &sh->dev[i].flags); clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state); set_bit(STRIPE_HANDLE, &sh->state);
raid5_release_stripe(sh); raid5_release_stripe(sh);
bio_reset(bi);
} }
static void raid5_end_write_request(struct bio *bi) static void raid5_end_write_request(struct bio *bi)
...@@ -2498,6 +2498,7 @@ static void raid5_end_write_request(struct bio *bi) ...@@ -2498,6 +2498,7 @@ static void raid5_end_write_request(struct bio *bi)
if (sh->batch_head && bi->bi_error && !replacement) if (sh->batch_head && bi->bi_error && !replacement)
set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state); set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state);
bio_reset(bi);
if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags)) if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
clear_bit(R5_LOCKED, &sh->dev[i].flags); clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state); set_bit(STRIPE_HANDLE, &sh->state);
...@@ -2505,7 +2506,6 @@ static void raid5_end_write_request(struct bio *bi) ...@@ -2505,7 +2506,6 @@ static void raid5_end_write_request(struct bio *bi)
if (sh->batch_head && sh != sh->batch_head) if (sh->batch_head && sh != sh->batch_head)
raid5_release_stripe(sh->batch_head); raid5_release_stripe(sh->batch_head);
bio_reset(bi);
} }
static void raid5_build_block(struct stripe_head *sh, int i, int previous) static void raid5_build_block(struct stripe_head *sh, int i, int previous)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment