]> git.hungrycats.org Git - linux/commit
btrfs: raid56: do not unhash a cached rbio that has rbios plugged on it misc-next/topics/raid56-fixes
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 12 Sep 2026 11:17:54 +0000 (07:17 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:19 +0000 (17:36 -0400)
commita965f2b78aa4d6e7c9f361010a43a2944b53405c
tree7cb5dae0255d728655d3d533d070da5d362b2ff6
parent4b5c3439b1cb4c08493c6b94e26d8cd4c1a39a80
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