]> git.hungrycats.org Git - linux/commit
btrfs: raid56: do not unhash a cached rbio that has rbios plugged on it 6.18/topics/raid56-fixes
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 12 Sep 2026 11:17:51 +0000 (07:17 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Wed, 16 Sep 2026 21:40:00 +0000 (17:40 -0400)
commit70e930d3cccfb62956b702b2465d369cb62bf4a1
tree8ce6547a5b794fa97ead3bc63dcb2440201079a4
parent33810a3056f6169d6b060b8f56ec5dd6559b576d
btrfs: raid56: do not unhash a cached rbio that has rbios plugged on it

unlock_stripe() caches the finished rbio with cache_rbio() before it
retakes the bucket and bio_list locks, and RBIO_RMW_LOCKED_BIT is still
set at that point.  A lock_stripe_add() for the same full stripe that
runs in that window finds a cached rbio it can neither steal (still RMW
locked) nor merge with (cached) and plugs itself onto it, which is
correct: unlock_stripe() then sees the plug list and hands the stripe
lock on to the plugged rbio.

But if the rbio is removed from the cache in that same window --
btrfs_raid56_uncache_range() from the commit's unpin, or the cache's own
shrink in cache_rbio() -- __remove_rbio_from_cache() finds an empty
bio_list, takes the rbio off the hash list, drops the hash reference and
hits BUG_ON(!list_empty(&rbio->plug_list)).  Seen on a degraded raid5
under fsstress: the transaction kthread died in that BUG_ON with the
bucket lock held and the rmw workers spun on it until the machine was
reset.

An rbio with rbios plugged on it is busy, like one with bios: leave it
on the hash list and let unlock_stripe() hand the lock on; drop only the
cache's reference here.

Assisted-by: Claude:claude-opus-4-8
fs/btrfs/raid56.c