Commit fee89f17 authored by NeilBrown's avatar NeilBrown Committed by Greg Kroah-Hartman

md/raid1: Don't use next_resync to determine how far resync has progressed

commit 23554960 upstream.

next_resync is (approximately) the location for the next resync request.
However it does *not* reliably determine the earliest location
at which resync might be happening.
This is because resync requests can complete out of order, and
we only limit the number of current requests, not the distance
from the earliest pending request to the latest.

mddev->curr_resync_completed is a reliable indicator of the earliest
position at which resync could be happening.   It is updated less
frequently, but is actually reliable which is more important.

So use it to determine if a write request is before the region
being resynced and so safe from conflict.

This error can allow resync IO to interfere with normal IO which
could lead to data corruption. Hence: stable.

Fixes: 79ef3a8aSigned-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0fdbd42f
...@@ -875,12 +875,10 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio) ...@@ -875,12 +875,10 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio)
if (conf->array_frozen || !bio) if (conf->array_frozen || !bio)
wait = true; wait = true;
else if (conf->barrier && bio_data_dir(bio) == WRITE) { else if (conf->barrier && bio_data_dir(bio) == WRITE) {
if (conf->next_resync < RESYNC_WINDOW_SECTORS) if ((conf->mddev->curr_resync_completed
wait = true; >= bio_end_sector(bio)) ||
else if ((conf->next_resync - RESYNC_WINDOW_SECTORS (conf->next_resync + NEXT_NORMALIO_DISTANCE
>= bio_end_sector(bio)) || <= bio->bi_iter.bi_sector))
(conf->next_resync + NEXT_NORMALIO_DISTANCE
<= bio->bi_iter.bi_sector))
wait = false; wait = false;
else else
wait = true; wait = true;
...@@ -918,7 +916,7 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) ...@@ -918,7 +916,7 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
if (bio && bio_data_dir(bio) == WRITE) { if (bio && bio_data_dir(bio) == WRITE) {
if (bio->bi_iter.bi_sector >= if (bio->bi_iter.bi_sector >=
conf->next_resync) { conf->mddev->curr_resync_completed) {
if (conf->start_next_window == MaxSector) if (conf->start_next_window == MaxSector)
conf->start_next_window = conf->start_next_window =
conf->next_resync + conf->next_resync +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment