Re: [PATCH v2 3/4] btrfs: zoned: drop stranded dirty metadata buffers at unmount
Boris Burkov <[email protected]> Thu, 23 Jul 2026 10:02:18 -0700
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Jul 23, 2026 at 05:54:27PM +0200, Johannes Thumshirn wrote: > On a zoned filesystem a freed tree block is kept dirty and flagged > EXTENT_BUFFER_ZONED_ZEROOUT so a later writeback zeroes it out and > advances the zone write pointer. Unsynced tree-log updates (e.g. from > rename or link) leave such buffers behind when the log is freed at > commit, and across log generations they can end up ahead of the write > pointer behind a hole, so btree_writepages() can never write them. > During normal operation the space is later reclaimed by a zone reset; at > unmount it is not, and the buffers survive to the final iput() of the > btree inode, which hangs in folio_wait_writeback() once the endio > workqueues are stopped. > > They cannot be written back from where they are freed (free_log_tree(), > inside the committing transaction) without deadlocking against that > commit, and they are stale anyway, not referenced by the committed > superblock. Drop their dirty state in close_ctree(), before > btrfs_stop_all_workers(). > Immediate fix looks fine, but the underlying issue is a little hacky. Can we detect that we have staled them from free_log_tree() and release the dirty there? Am I correct in understanding that this means we can overestimate dirty? By an arbitrary amount if I do lots of unsynced tree log updates? Either way, Reviewed-by: Boris Burkov > Signed-off-by: Johannes Thumshirn <[email protected]> > --- > fs/btrfs/disk-io.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 8d0afc2842cc..01d01e10d000 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -4549,6 +4549,13 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) > free_root_pointers(fs_info, true); > btrfs_free_fs_roots(fs_info); > > + /* > + * Drop metadata left stranded ahead of a zone write pointer while the > + * endio workqueues are still up, so the final iput() of the btree inode > + * below does not hang submitting a write that can no longer complete. > + */ > + btrfs_zoned_release_dirty_metadata(fs_info); > + > /* > * We must make sure there is not any read request to > * submit after we stop all workers. > -- > 2.55.0 >