diff options
author | NeilBrown <neilb@suse.de> | 2012-11-21 00:33:40 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-11-21 17:14:13 -0500 |
commit | ca64cae96037de16e4af92678814f5d4bf0c1c65 (patch) | |
tree | b789332f018682bbab38981d3bd95b8a0129f5e9 /drivers/md | |
parent | ef5b7c69b7a1b8b8744a6168b6ff02900f81b6ca (diff) |
md/raid5: Make sure we clear R5_Discard when discard is finished.
commit 9e44476851e91c86c98eb92b9bc27fb801f89072
MD: raid5 avoid unnecessary zero page for trim
change raid5 to clear R5_Discard when the complete request is
handled rather than when submitting the per-device discard request.
However it did not clear R5_Discard for the parity device.
This means that if the stripe_head was reused before it expired from
the cache, the setting would be wrong and a hang would result.
Also if the R5_Uptodate bit happens to be set, R5_Discard again
won't be cleared. But R5_Uptodate really should be clear at this point.
So make sure R5_Discard is cleared in all cases, and clear
R5_Uptodate when a 'discard' completes.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 0fb988556eea..a4502686e7a8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf, | |||
2774 | dev = &sh->dev[i]; | 2774 | dev = &sh->dev[i]; |
2775 | if (!test_bit(R5_LOCKED, &dev->flags) && | 2775 | if (!test_bit(R5_LOCKED, &dev->flags) && |
2776 | (test_bit(R5_UPTODATE, &dev->flags) || | 2776 | (test_bit(R5_UPTODATE, &dev->flags) || |
2777 | test_and_clear_bit(R5_Discard, &dev->flags))) { | 2777 | test_bit(R5_Discard, &dev->flags))) { |
2778 | /* We can return any write requests */ | 2778 | /* We can return any write requests */ |
2779 | struct bio *wbi, *wbi2; | 2779 | struct bio *wbi, *wbi2; |
2780 | pr_debug("Return write for disc %d\n", i); | 2780 | pr_debug("Return write for disc %d\n", i); |
2781 | if (test_and_clear_bit(R5_Discard, &dev->flags)) | ||
2782 | clear_bit(R5_UPTODATE, &dev->flags); | ||
2781 | wbi = dev->written; | 2783 | wbi = dev->written; |
2782 | dev->written = NULL; | 2784 | dev->written = NULL; |
2783 | while (wbi && wbi->bi_sector < | 2785 | while (wbi && wbi->bi_sector < |
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf, | |||
2795 | !test_bit(STRIPE_DEGRADED, &sh->state), | 2797 | !test_bit(STRIPE_DEGRADED, &sh->state), |
2796 | 0); | 2798 | 0); |
2797 | } | 2799 | } |
2798 | } | 2800 | } else if (test_bit(R5_Discard, &sh->dev[i].flags)) |
2801 | clear_bit(R5_Discard, &sh->dev[i].flags); | ||
2799 | 2802 | ||
2800 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) | 2803 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) |
2801 | if (atomic_dec_and_test(&conf->pending_full_writes)) | 2804 | if (atomic_dec_and_test(&conf->pending_full_writes)) |