From: ChangSyun Peng allenpeng@synology.com
commit a1c6ae3d9f3dd6aa5981a332a6f700cf1c25edef upstream.
In degraded raid5, we need to read parity to do reconstruct-write when data disks fail. However, we can not read parity from handle_stripe_dirtying() in force reconstruct-write mode.
Reproducible Steps:
1. Create degraded raid5 mdadm -C /dev/md2 --assume-clean -l5 -n3 /dev/sda2 /dev/sdb2 missing 2. Set rmw_level to 0 echo 0 > /sys/block/md2/md/rmw_level 3. IO to raid5
Now some io may be stuck in raid5. We can use handle_stripe_fill() to read the parity in this situation.
Cc: stable@vger.kernel.org # v4.4+ Reviewed-by: Alex Wu alexwu@synology.com Reviewed-by: BingJing Chang bingjingc@synology.com Reviewed-by: Danny Shih dannyshih@synology.com Signed-off-by: ChangSyun Peng allenpeng@synology.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/md/raid5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3345,6 +3345,7 @@ static int need_this_block(struct stripe * is missing/faulty, then we need to read everything we can. */ if (sh->raid_conf->level != 6 && + sh->raid_conf->rmw_level != PARITY_DISABLE_RMW && sh->sector < sh->raid_conf->mddev->recovery_cp) /* reconstruct-write isn't being forced */ return 0; @@ -4479,7 +4480,7 @@ static void handle_stripe(struct stripe_ * or to load a block that is being partially written. */ if (s.to_read || s.non_overwrite - || (conf->level == 6 && s.to_write && s.failed) + || (s.to_write && s.failed) || (s.syncing && (s.uptodate + s.compute < disks)) || s.replacing || s.expanding)