]> git.hungrycats.org Git - linux/commit
btrfs: raid56: keep a reference on a stolen cached rbio until it is dropped
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Sat, 5 Sep 2026 02:14:19 +0000 (22:14 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:19 +0000 (17:36 -0400)
commit4b5c3439b1cb4c08493c6b94e26d8cd4c1a39a80
treead0c9b1a1b6a05985dab63a77572316d07273eea
parentab5820231fa8d8c9455801c75b03f3cf99931bca
btrfs: raid56: keep a reference on a stolen cached rbio until it is dropped

lock_stripe_add() steals the pages of a cached rbio for the same full
stripe, drops the rbio's hash-list reference under the bucket lock, and
only after releasing that lock calls remove_rbio_from_cache() on it.
Between those two steps the rbio is held by nothing but the cache
reference, and anyone who removes it from the cache in that window --
the cache shrink in cache_rbio(), or btrfs_raid56_uncache_range() when
the stripe's extents are freed -- frees it.  remove_rbio_from_cache()
then dereferences a freed rbio:

  BUG: kernel NULL pointer dereference, address: 0000000000000008
  Workqueue: btrfs-rmw rmw_rbio_work
  RIP: 0010:__remove_rbio_from_cache+0x33/0x180
   remove_rbio_from_cache+0x41/0x60
   lock_stripe_add+0xfc/0x460
   rmw_rbio_work+0x35/0x400

The oops leaves the cache and bucket locks held, and every other RMW
worker and the transaction thread soft-lock behind them.  Seen after
8h of the device-corruption acceptance suite on 6.18, where freeing of
extents during read errors made the uncache path frequent; the window
exists with the plain cache shrink as well.

Keep the hash-list reference across the steal and drop it after the
cache removal, so a concurrent remover can clear the cache bit and drop
its own reference but never free the rbio under our feet.

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