summaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-09-20 09:35:22 +0100
committerDave Airlie <airlied@redhat.com>2011-09-20 09:35:22 +0100
commitb2d108ba333cdff80d9e7645d7697cbb6bb0fc29 (patch)
treef62b2464a35e4676b5e3e9ef340758a17d0b80f8 /drivers/md/raid10.c
parentfcf4de5acf09889e3f0c131ebe385c983006d71b (diff)
parenta0d9a8feb928465f3cb525a19e5fafd06ef66ced (diff)
Merge branch 'drm-nouveau-next' of git://git.freedesktop.org/git/nouveau/linux-2.6 into drm-next
* 'drm-nouveau-next' of git://git.freedesktop.org/git/nouveau/linux-2.6: (353 commits) drm/nouveau: remove allocations from gart populate() hook drm/nvc0/fb: slightly improve PMFB intr handling, move out of nvc0_graph.c drm/nvc0/fifo: avoid touching missing subfifos drm/nvd9/disp: bail out of mode_set_base if no fb bound to crtc drm/nvd9/disp: stub some more api hooks so we don't oops on resume drm/nouveau: fix printk typo in ioremap failure path drm/nvc0/pm: minor clock readback fixes drm/nv40/pm: execute memory reset script from vbios drm/nv50/gr: refactor initialisation drm/nouveau: if requested, try harder at disabling sysmem pushbufs drm/nv50/gr: enable ctxprog xfer only when we need it to save power drm/nouveau/dp: add support for displayport table 0x30 drm/nouveau/dp: return master dp table pointer too when looking up encoder drm/nouveau/bios: simplify U/d table hash matching func to just match drm/nouveau/dp: preserve non-pattern bits in DP_TRAINING_PATTERN_SET drm/nvc0/gr: remove MODULE_FIRMWARE() lines drm/nouveau/dp: use alternate lane mask for nvaf drm/nouveau/dp: link rate scripts are selected with a comparison table drm/nv40/pm: write nv40-specific reclocking routines drm/nv40/pm: parse geometric delta clock from vbios ...
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r--drivers/md/raid10.c47
1 files changed, 24 insertions, 23 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 8b29cd4f01c..d7a8468ddea 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,20 +1132,12 @@ 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);
- }
-
- /* In case raid10d snuck in to freeze_array */
- wake_up(&conf->wait_barrier);
+ /* Don't remove the bias on 'remaining' (one_write_done) until
+ * after checking if we need to go around again.
+ */
if (sectors_handled < (bio->bi_size >> 9)) {
+ one_write_done(r10_bio);
/* We need another r10_bio. It has already been counted
* in bio->bi_phys_segments.
*/
@@ -1154,6 +1151,10 @@ retry_write:
r10_bio->state = 0;
goto retry_write;
}
+ one_write_done(r10_bio);
+
+ /* In case raid10d snuck in to freeze_array */
+ wake_up(&conf->wait_barrier);
if (do_sync || !mddev->bitmap || !plugged)
md_wakeup_thread(mddev->thread);