Skip to content

Commit c916ca3

Browse files
YuKuai-huaweiliu-song-6
authored andcommitted
md/raid1: Fix data corruption for degraded array with slow disk
read_balance() will avoid reading from slow disks as much as possible, however, if valid data only lands in slow disks, and a new normal disk is still in recovery, unrecovered data can be read: raid1_read_request read_balance raid1_should_read_first -> return false choose_best_rdev -> normal disk is not recovered, return -1 choose_bb_rdev -> missing the checking of recovery, return the normal disk -> read unrecovered data Root cause is that the checking of recovery is missing in choose_bb_rdev(). Hence add such checking to fix the problem. Also fix similar problem in choose_slow_rdev(). Cc: [email protected] Fixes: 9f3ced7 ("md/raid1: factor out choose_bb_rdev() from read_balance()") Fixes: dfa8ecd ("md/raid1: factor out choose_slow_rdev() from read_balance()") Reported-and-tested-by: Mateusz Jończyk <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Yu Kuai <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Song Liu <[email protected]>
1 parent 7db4042 commit c916ca3

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

drivers/md/raid1.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,12 @@ static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio,
617617
return -1;
618618
}
619619

620+
static bool rdev_in_recovery(struct md_rdev *rdev, struct r1bio *r1_bio)
621+
{
622+
return !test_bit(In_sync, &rdev->flags) &&
623+
rdev->recovery_offset < r1_bio->sector + r1_bio->sectors;
624+
}
625+
620626
static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio,
621627
int *max_sectors)
622628
{
@@ -635,6 +641,7 @@ static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio,
635641

636642
rdev = conf->mirrors[disk].rdev;
637643
if (!rdev || test_bit(Faulty, &rdev->flags) ||
644+
rdev_in_recovery(rdev, r1_bio) ||
638645
test_bit(WriteMostly, &rdev->flags))
639646
continue;
640647

@@ -673,7 +680,8 @@ static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio,
673680

674681
rdev = conf->mirrors[disk].rdev;
675682
if (!rdev || test_bit(Faulty, &rdev->flags) ||
676-
!test_bit(WriteMostly, &rdev->flags))
683+
!test_bit(WriteMostly, &rdev->flags) ||
684+
rdev_in_recovery(rdev, r1_bio))
677685
continue;
678686

679687
/* there are no bad blocks, we can use this disk */
@@ -733,9 +741,7 @@ static bool rdev_readable(struct md_rdev *rdev, struct r1bio *r1_bio)
733741
if (!rdev || test_bit(Faulty, &rdev->flags))
734742
return false;
735743

736-
/* still in recovery */
737-
if (!test_bit(In_sync, &rdev->flags) &&
738-
rdev->recovery_offset < r1_bio->sector + r1_bio->sectors)
744+
if (rdev_in_recovery(rdev, r1_bio))
739745
return false;
740746

741747
/* don't read from slow disk unless have to */

0 commit comments

Comments
 (0)