diff options
author | NeilBrown <neilb@suse.de> | 2011-09-10 09:21:17 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-09-10 09:21:17 +0200 |
commit | 19d5f834d6aff7efb1c9353523865c5bce869470 (patch) | |
tree | 01c18b17519df9034bbcaf126eac9d9318143a1d | |
parent | Avoid dereferencing a 'request_queue' after last close. (diff) | |
download | linux-19d5f834d6aff7efb1c9353523865c5bce869470.tar.xz linux-19d5f834d6aff7efb1c9353523865c5bce869470.zip |
md/raid10: unify handling of write completion.
A write can complete at two different places:
1/ when the last member-device write completes, through
raid10_end_write_request
2/ in make_request() when we remove the initial bias from ->remaining.
These two should do exactly the same thing and the comment says they
do, but they don't.
So factor the correct code out into a function and call it in both
places. This makes the code much more similar to RAID1.
The difference is only significant if there is an error, and they
usually take a while, so it is unlikely that there will be an error
already when make_request is completing, so this is unlikely to cause
real problems.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid10.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8b29cd4f01c8..f6873fc8e5ee 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -337,6 +337,21 @@ static void close_write(r10bio_t *r10_bio) md_write_end(r10_bio->mddev); } +static void one_write_done(r10bio_t *r10_bio) +{ + if (atomic_dec_and_test(&r10_bio->remaining)) { + if (test_bit(R10BIO_WriteError, &r10_bio->state)) + reschedule_retry(r10_bio); + else { + close_write(r10_bio); + if (test_bit(R10BIO_MadeGood, &r10_bio->state)) + reschedule_retry(r10_bio); + else + raid_end_bio_io(r10_bio); + } + } +} + static void raid10_end_write_request(struct bio *bio, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); @@ -387,17 +402,7 @@ static void raid10_end_write_request(struct bio *bio, int error) * Let's see if all mirrored write operations have finished * already. */ - if (atomic_dec_and_test(&r10_bio->remaining)) { - if (test_bit(R10BIO_WriteError, &r10_bio->state)) - reschedule_retry(r10_bio); - else { - close_write(r10_bio); - if (test_bit(R10BIO_MadeGood, &r10_bio->state)) - reschedule_retry(r10_bio); - else - raid_end_bio_io(r10_bio); - } - } + one_write_done(r10_bio); if (dec_rdev) rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); } @@ -1127,15 +1132,8 @@ retry_write: spin_unlock_irqrestore(&conf->device_lock, flags); } - if (atomic_dec_and_test(&r10_bio->remaining)) { - /* This matches the end of raid10_end_write_request() */ - bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector, - r10_bio->sectors, - !test_bit(R10BIO_Degraded, &r10_bio->state), - 0); - md_write_end(mddev); - raid_end_bio_io(r10_bio); - } + /* Remove the bias on 'remaining' */ + one_write_done(r10_bio); /* In case raid10d snuck in to freeze_array */ wake_up(&conf->wait_barrier); |