]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
md/raid1: fix: IO can block resync indefinitely
authorNeilBrown <neilb@suse.com>
Tue, 8 Nov 2016 23:21:32 +0000 (10:21 +1100)
committerShaohua Li <shli@fb.com>
Wed, 9 Nov 2016 20:53:24 +0000 (12:53 -0800)
While performing a resync/recovery, raid1 divides the
array space into three regions:
 - before the resync
 - at or shortly after the resync point
 - much further ahead of the resync point.

Write requests to the first or third do not need to wait.  Write
requests to the middle region do need to wait if resync requests are
pending.

If there are any active write requests in the middle region, resync
will wait for them.

Due to an accounting error, there is a small range of addresses,
between conf->next_resync and conf->start_next_window, where write
requests will *not* be blocked, but *will* be counted in the middle
region.  This can effectively block resync indefinitely if filesystem
writes happen repeatedly to this region.

As ->next_window_requests is incremented when the sector is after
  conf->start_next_window + NEXT_NORMALIO_DISTANCE
the same boundary should be used for determining when write requests
should wait.

Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/raid1.c

index aac2a05cf8d15cbdf5a82aa91fe32e1256602b64..9ac61cd85e5ca66f0a83792905ccf6202a01fdb7 100644 (file)
@@ -834,7 +834,7 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio)
        else if (conf->barrier && bio_data_dir(bio) == WRITE) {
                if ((conf->mddev->curr_resync_completed
                     >= bio_end_sector(bio)) ||
-                   (conf->next_resync + NEXT_NORMALIO_DISTANCE
+                   (conf->start_next_window + NEXT_NORMALIO_DISTANCE
                     <= bio->bi_iter.bi_sector))
                        wait = false;
                else