Re: [PATCH v3] md/raid5: fix reshape deadlock while failed devices more than max degraded

"yu kuai" <[email protected]>
Newsgroups gmane.linux.raid,gmane.linux.kernel
Message-ID <[email protected]>
在 2026/6/24 15:58, Chen Cheng 写道:

> From: Chen Cheng<[email protected]>
>
> reshape stripe lifetime:
> - start reshape ==> reshape_request():
> 	* get destination stripe,
> 	  - if need to copy source data chunks, set STRIPE_EXPANDING;
> 	  - or, if new regions past the old end of the array, zero-filled,
> 	    no need source data, set STRIPE_EXPANDING | STRIPE_READY
> 	* get source stripe,
> 	  - set STRIPE_EXPAND_SOURCE
>
> - handle expand stripe ==> handle_stripe():
> 	reshape use reconstruct-write to construct stripe,
> 	four stages:
> 	1. prepare source data chunks for old geometry stripe
> 		- fill source stripe data by read or compute
> 	2. move data from old geometry source stripe to new geometry
> 	   destination stripe
> 		- source stripe clear STRIPE_EXPAND_SOURCE
> 		- drain data from source to destination stripe
> 		- mark stripe chunk as R5_Expanded|R5_UPTODATE when the
> 		  drain from source chunk to destionation chunk is completed
> 		- all stripe chunks drain are completed, then mark
> 		  STRIPE_EXPAND_READY
> 	3. calculate p/q chunks for destination stripe
> 		- if destination stripe does't depends on source dstripe,
> 		  then we can clear STRIPE_EXPANDING
> 	4. write-out to disks and release
> 		- set R5_Wantwrite|R5_Locked, writeout to disk
> 		- if write-out successed, clear STRIPE_EXPAND_READY, and
> 		  decrement reshape_stripe, call md_done_sync() to report
> 		  reshape progress.
>
> 1. cleanup the following kinds of **destination stripe**
> 	when failed device more than max degraded:
>    - new regions past the old end of the array, zero-filled in place,
>      requires no source data.
> 	(STRIPE_EXPANDING | STRIPE_EXPAND_READY)
>    - prepare source data chunks already done, and writeout failed
> 	(STRIPE_EXPAND_READY)
>
> 2. destination stripes that need source data
> 	(STRIPE_EXPANDING, no STRIPE_HANDLE)
>    - these kind of stripes sit idle in the stripe cache and are never seen
>      by handle_stripe(). So clean up indirectly when thier source stripe
>      (type 3) is processed.
>
> 3. source stripes (STRIPE_EXPAND_SOURCE)
>    - hit handle_stripe() after thier member disks are markded Faulty.
>    - clear STRIPE_EXPAND_SOURCE, finds and cleanup all dependent destination
>      stripes that were waiting for data.
>    - walks the source's data disks, compute the corresponding destination
>      sector, looks up the destination stripe, and do cleanup(clear flags,
>      dec counters, call md_done_sync())
>
> Reproducer:
>    - Create a 4-disk RAID5 with mdadm on top of 5 disposable test disks
>      wrapped by dm targets.
>    - Add the 5th device as a spare and start a 4 -> 5 reshape.
>    - Wait until /sys/block/mdX/md/sync_action reports "reshape".
>    - Inject failures on two members so reshape exceeds max_degraded.
>    - After a few seconds, write "frozen" to /sys/block/mdX/md/sync_action.
>      Before this fix, the write blocks indefinitely.
>
> Read-error variant:
>    - Use dm-dust on /dev/sd[b-f].
>    - Preload bad blocks on two source members, e.g. dust0 and dust1:
>        dmsetup message dust0 0 addbadblock <range>
>        dmsetup message dust1 0 addbadblock <range>
>    - Start reshape:
>        mdadm -C /dev/mdX -e 1.2 -l 5 -n 4 -c 64 --assume-clean /dev/mapper/dust{0..3}
>        mdadm --manage /dev/mdX --add /dev/mapper/dust4
>        mdadm --grow /dev/mdX -n 5 --backup-file=/tmp/grow.backup &
>    - Once reshape starts, enable the injected read failures:
>        dmsetup message dust0 0 enable
>        dmsetup message dust1 0 enable
>    - Then:
>        echo frozen > /sys/block/mdX/md/sync_action
>      hangs forever before the fix.
>
> Write-error variant:
>    - Use dm-flakey on /dev/sd[b-f].
>    - Start the same 4 -> 5 reshape on flakey0..flakey4.
>    - Once reshape starts, switch two members, e.g. flakey3 and flakey4,
>      to error_writes.
>    - Then:
>        echo frozen > /sys/block/mdX/md/sync_action
>      hangs forever before the fix.
>
> md_do_sync() exits its main loop on MD_RECOVERY_INTR but then blocks
> forever at:
>
>    wait_event(mddev->recovery_wait,
> 		!atomic_read(&mddev->recovery_active));
>
> After the fix recovery_active drains to zero, md_do_sync() prints
>
>      md/raid:md0: Cannot continue operation (2/5 failed).
>      md: md0: reshape interrupted.
>
> v2 -> v3:
> - just kick sashiko-bot to review my patch..
>
> changes v1 -> v2:
> - handle reshape write deadlock while failed devices more than max degraded
>
> Signed-off-by: Chen Cheng<[email protected]>
> ---
>   drivers/md/raid5.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 74 insertions(+)
Reviewed-by: Yu Kuai <[email protected]>

-- 
Thanks,
Kuai
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.