diff options
author | NeilBrown <neilb@suse.de> | 2011-07-26 21:00:36 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-07-26 21:00:36 -0400 |
commit | 8cfa7b0f67b4d899efc7f39eb7e172fd79237811 (patch) | |
tree | df1002e5eccbf4b241dc9e948bb894de2106d6e2 /drivers/md/raid5.c | |
parent | cbea21703b2484f83faef040ed1de30114794392 (diff) |
md/raid5: Avoid BUG caused by multiple failures.
While preparing to write a stripe we keep the parity block or blocks
locked (R5_LOCKED) - towards the end of schedule_reconstruction.
If the array is discovered to have failed before this write completes
we can leave those blocks LOCKED, and init_stripe will notice that a
free stripe still has a locked block and will complain.
So clear the R5_LOCKED flag in handle_failed_stripe, and demote the
'BUG' to a 'WARN_ON'.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a81eca6434dd..b874f42694e2 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -340,7 +340,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous) | |||
340 | (unsigned long long)sh->sector, i, dev->toread, | 340 | (unsigned long long)sh->sector, i, dev->toread, |
341 | dev->read, dev->towrite, dev->written, | 341 | dev->read, dev->towrite, dev->written, |
342 | test_bit(R5_LOCKED, &dev->flags)); | 342 | test_bit(R5_LOCKED, &dev->flags)); |
343 | BUG(); | 343 | WARN_ON(1); |
344 | } | 344 | } |
345 | dev->flags = 0; | 345 | dev->flags = 0; |
346 | raid5_build_block(sh, i, previous); | 346 | raid5_build_block(sh, i, previous); |
@@ -2301,6 +2301,10 @@ handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh, | |||
2301 | if (bitmap_end) | 2301 | if (bitmap_end) |
2302 | bitmap_endwrite(conf->mddev->bitmap, sh->sector, | 2302 | bitmap_endwrite(conf->mddev->bitmap, sh->sector, |
2303 | STRIPE_SECTORS, 0, 0); | 2303 | STRIPE_SECTORS, 0, 0); |
2304 | /* If we were in the middle of a write the parity block might | ||
2305 | * still be locked - so just clear all R5_LOCKED flags | ||
2306 | */ | ||
2307 | clear_bit(R5_LOCKED, &sh->dev[i].flags); | ||
2304 | } | 2308 | } |
2305 | 2309 | ||
2306 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) | 2310 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) |