Re: [PATCH v2] btrfs: flush the fixup workers during close_ctree
David Sterba <[email protected]> Fri, 31 Jul 2026 13:06:35 +0200
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Jul 30, 2026 at 09:38:02AM -0700, Boris Burkov wrote:
> Reintroducing the COW fixup worker brought back the unmount race fixed
> by commit 41fd1e94066a ("btrfs: wait for fixup workers before stopping
> cleaner kthread during umount") without bringing back the fix.
>
> A fixup work item queued by the final writeback pass can still be in flight
> when close_ctree() stops the cleaner kthread and frees the fs roots.
> While destroy_workqueue() drains the queue, that happens after the
> cleaner thread was freed, so btrfs_add_delayed_iput() called from the
> fixup worker is no longer safe (not to mention that we are already in
> BTRFS_FS_STATE_NO_DELAYED_IPUT when it runs).
>
> Therefore we need to bring back explicitly flushing the fixup workqueue
> as in Filipe's original fix. The first flush will catch all the fixup
> writeback queued during the final sync before umount, but some of that
> might hit memory allocation errors and stay fixup in the blocks/folio,
> leading any subsequent writeback triggered *inside* umount (e.g. reclaim
> workers shutting down) to hit it and queue again. To fix that, and the
> possibility of any really long-lived pinned folios getting marked, deny
> queueing new fixup during umount. That allows us to flush twice (once
> before doing a real writeback pass to get the actual data, second time
> to clean up any rather unlikely stragglers right before declaring
> BTRFS_FS_STATE_NO_DELAYED_IPUT) and be certain nothing got re-queued.
>
> Reproduced by injecting a one-shot 30s sleep at the head of
> btrfs_writepage_fixup_worker() on a KASAN kernel, running the normal
> reproducing read dio workload before unmount and then observing:
>
> BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x35/0x50
> Read of size 1 at addr ffff88810b4b08f8 by task kworker/u32:5/219
> Workqueue: btrfs-fixup btrfs_writepage_fixup_worker [btrfs]
> Call Trace:
> _raw_spin_lock_irqsave+0x35/0x50
> try_to_wake_up+0xc0/0x18c0
> btrfs_writepage_fixup_worker+0x7f3/0xf20 [btrfs]
> ...
>
> Fixes: 4be9c7da6860 ("btrfs: trigger cow fixup via dirty_folio()")
BTW the commit is not stable, so you can only use the subject for
reference.
As the new fixup worker commit is already big, please add this one
separately.