Commit c467e97f authored by David Jeffery's avatar David Jeffery Committed by Song Liu

md/raid6: use valid sector values to determine if an I/O should wait on the reshape

During a reshape or a RAID6 array such as expanding by adding an additional
disk, I/Os to the region of the array which have not yet been reshaped can
stall indefinitely. This is from errors in the stripe_ahead_of_reshape
function causing md to think the I/O is to a region in the actively
undergoing the reshape.

stripe_ahead_of_reshape fails to account for the q disk having a sector
value of 0. By not excluding the q disk from the for loop, raid6 will always
generate a min_sector value of 0, causing a return value which stalls.

The function's max_sector calculation also uses min() when it should use
max(), causing the max_sector value to always be 0. During a backwards
rebuild this can cause the opposite problem where it allows I/O to advance
when it should wait.

Fixing these errors will allow safe I/O to advance in a timely manner and
delay only I/O which is unsafe due to stripes in the middle of undergoing
the reshape.

Fixes: 486f6055 ("md/raid5: Check all disks in a stripe_head for reshape progress")
Cc: stable@vger.kernel.org # v6.0+
Signed-off-by: default avatarDavid Jeffery <djeffery@redhat.com>
Tested-by: default avatarLaurence Oberman <loberman@redhat.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20231128181233.6187-1-djeffery@redhat.com
parent 45b47895
...@@ -5892,11 +5892,11 @@ static bool stripe_ahead_of_reshape(struct mddev *mddev, struct r5conf *conf, ...@@ -5892,11 +5892,11 @@ static bool stripe_ahead_of_reshape(struct mddev *mddev, struct r5conf *conf,
int dd_idx; int dd_idx;
for (dd_idx = 0; dd_idx < sh->disks; dd_idx++) { for (dd_idx = 0; dd_idx < sh->disks; dd_idx++) {
if (dd_idx == sh->pd_idx) if (dd_idx == sh->pd_idx || dd_idx == sh->qd_idx)
continue; continue;
min_sector = min(min_sector, sh->dev[dd_idx].sector); min_sector = min(min_sector, sh->dev[dd_idx].sector);
max_sector = min(max_sector, sh->dev[dd_idx].sector); max_sector = max(max_sector, sh->dev[dd_idx].sector);
} }
spin_lock_irq(&conf->device_lock); spin_lock_irq(&conf->device_lock);
......
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