diff options
| author | Chen Cheng <chencheng@fnnas.com> | 2026-06-23 15:59:40 +0800 |
|---|---|---|
| committer | Yu Kuai <yukuai@fygo.io> | 2026-07-30 16:28:11 +0800 |
| commit | e12e619c2e2d0c3f42b14e9ef1ab778e696ffffd (patch) | |
| tree | 11465c6e95c19fe933dda79095de7d89d2b2d0c1 | |
| parent | 371f7a1b392edc8b7cf449cc7713179b588f2d0e (diff) | |
| download | linux-e12e619c2e2d0c3f42b14e9ef1ab778e696ffffd.tar.gz linux-e12e619c2e2d0c3f42b14e9ef1ab778e696ffffd.zip | |
md/raid1: protect sequential read hints for read balance
The patch just suppress KCSAN noise. No functional change.
KCSAN reports a race, point to update_read_sectors() update next_seq_sect vs.
read next_seq_sect.
Protect next_seq_sect and seq_start with READ_ONCE/WRITE_ONCE, otherwise,
read balance see stale sequential-read hints.
KCSAN report:
==============
BUG: KCSAN: data-race in raid1_read_request / raid1_read_request
write to 0xffff8e3a2d6736d0 of 8 bytes by task 593784 on cpu 10:
raid1_read_request+0xe5a/0x19f0
raid1_make_request+0xdf/0x1990
md_handle_request+0x4a2/0xa40
[...]
read to 0xffff8e3a2d6736d0 of 8 bytes by task 593776 on cpu 11:
raid1_read_request+0xe3f/0x19f0
raid1_make_request+0xdf/0x1990
md_handle_request+0x4a2/0xa40
[...]
value changed: 0x0000000000356368 -> 0x0000000000356370
Signed-off-by: Chen Cheng <chencheng@fnnas.com>
Reviewed-by: Yu Kuai <yukuai@fygo.io>
Link: https://patch.msgid.link/20260623075940.2476255-1-chencheng@fnnas.com
Signed-off-by: Yu Kuai <yukuai@fygo.io>
| -rw-r--r-- | drivers/md/raid1.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index afe2ca96ad8c..4d7f33a2faaa 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -604,9 +604,9 @@ static void update_read_sectors(struct r1conf *conf, int disk, struct raid1_info *info = &conf->mirrors[disk]; atomic_inc(&info->rdev->nr_pending); - if (info->next_seq_sect != this_sector) - info->seq_start = this_sector; - info->next_seq_sect = this_sector + len; + if (READ_ONCE(info->next_seq_sect) != this_sector) + WRITE_ONCE(info->seq_start, this_sector); + WRITE_ONCE(info->next_seq_sect, this_sector + len); } static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio, @@ -735,8 +735,7 @@ static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio, static bool is_sequential(struct r1conf *conf, int disk, struct r1bio *r1_bio) { - /* TODO: address issues with this check and concurrency. */ - return conf->mirrors[disk].next_seq_sect == r1_bio->sector || + return READ_ONCE(conf->mirrors[disk].next_seq_sect) == r1_bio->sector || READ_ONCE(conf->mirrors[disk].head_position) == r1_bio->sector; } @@ -747,15 +746,18 @@ static bool is_sequential(struct r1conf *conf, int disk, struct r1bio *r1_bio) static bool should_choose_next(struct r1conf *conf, int disk) { struct raid1_info *mirror = &conf->mirrors[disk]; + sector_t seq_start, next_seq_sect; int opt_iosize; if (!test_bit(Nonrot, &mirror->rdev->flags)) return false; opt_iosize = bdev_io_opt(mirror->rdev->bdev) >> 9; - return opt_iosize > 0 && mirror->seq_start != MaxSector && - mirror->next_seq_sect > opt_iosize && - mirror->next_seq_sect - opt_iosize >= mirror->seq_start; + seq_start = READ_ONCE(mirror->seq_start); + next_seq_sect = READ_ONCE(mirror->next_seq_sect); + return opt_iosize > 0 && seq_start != MaxSector && + next_seq_sect > opt_iosize && + next_seq_sect - opt_iosize >= seq_start; } static bool rdev_readable(struct md_rdev *rdev, struct r1bio *r1_bio) |
