[PATCH v4 00/18] btrfs: remove the v1 space cache
From: Tal Zussman
Date: Mon Oct 12 2026 - 12:45:44 EST
Since commit 545e560a5b0f ("btrfs: disable v1 space cache") the mount
options can't select the v1 space cache anymore, but the code is all
still there, and a filesystem with an old cache and no free space tree
still enabled it from the superblock. Qu suggested removing it rather
than converting its page handling to folios [1].
Patch 1 fixes a pre-existing leak in the cleanup path, where a crash
before the delayed iput evicts a cache inode left it unreachable with
its link count still set.
Patch 2 stops enabling the cache from the on-disk state, so an existing
cache is cleaned up on the next read-write mount, as -o nospace_cache
already did. This is the one user-visible change: the cleanup is now
unconditional, and a read-write mount fails if it fails. There are two
ways to fix this failure:
1. Convert to the free space tree during mount (the recommended
conversion), but this could fail for the same reason.
2. Run 'btrfs rescue clear-space-cache v1' on an unmounted filesystem.
Patches 3-7 remove the write path, 8 and 9 the load path and
disk_cache_state, and 10 and 11 the SPACE_CACHE flag and the unused
half of the cleanup helper. Patches 12-17 remove the trimming ranges
and the free space inode special cases in the write path, which only
the v1 writer used. Patch 18 removes TRANS_JOIN_NOLOCK, which the space
cache was the only user of.
What's left is what's needed to find and delete the cache inodes of an
existing filesystem:
1. lookup_free_space_inode(), btrfs_remove_free_space_inode(), and
btrfs_cleanup_free_space_cache_v1(), which runs on the first
read-write mount and zeroes cache_generation in the super block.
2. btrfs_truncate_free_space_cache() and delete_v1_space_cache(), which
relocation uses to get a cache inode's extents out of a block group.
3. btrfs_is_free_space_inode(), for the evict and inode update paths.
4. The on-disk definitions: cache_generation in the super block,
BTRFS_FREE_SPACE_OBJECTID, and the free space header and entry
items.
space_cache and space_cache=v1 still fall back to nospace_cache with a
warning.
This also removes the page-based I/O in the free space code.
btrfs_io_ctl used a struct page array and was one of the last users
of clear_page_dirty_for_io().
Tested with fstests (btrfs and generic quick groups), with and without
the free space tree, with no regressions against the base kernel.
Upgrading from a filesystem with an existing v1 cache written by a 6.8
kernel was also tested. The cache is removed on the first read-write
mount and on remount from read-only, and the resulting filesystem is
clean under btrfs check and still mountable by the old kernel.
Based on the misc-next commit in btrfs for-next (a5c77fde6730).
[1] https://lore.kernel.org/linux-btrfs/e1dd5a75-9a67-4bc6-b8d8-bfff79b5b907@xxxxxxxx/
---
Changes in v4:
- Patch 1 (new): Write the zero link count when removing a free space
inode, so an interrupted cleanup can't leak it.
- Patch 2: Clear FREE_SPACE_TREE in btrfs_reconfigure() whenever the
free space tree is not on disk, so a remount that only warns about
the free space tree no longer leaves the option set, per Sashiko.
- Patch 2: Dropped review tag.
- Patch 16: Also drop the tree root check from the delalloc metadata
release.
- Patch 18: Redo against the TRANS_* flag cleanups in for-next.
- Link to v3: https://patch.msgid.link/20260916-btrfs-remove-v1-space-cache-v3-0-10ebde03b96f@xxxxxxxxxxxx
Changes in v3:
- Patch 5 (new): Keep the cache_write_mutex locking that serializes
btrfs_start_dirty_block_groups() with btrfs_remove_block_group(),
since it also protects the block group item update and not just the
cache writeout. Rename it to dirty_bgs_update_mutex.
- Patch 8: Drop the "Old style space inode found, converting." branch
from lookup_free_space_inode(), as it no longer converts anything.
- Link to v2: https://patch.msgid.link/20260913-btrfs-remove-v1-space-cache-v2-0-186767a7e106@xxxxxxxxxxxx
Changes in v2:
- Split the TRANS_JOIN_NOLOCK removal out of the ordered extent patch
into its own patch at the end of the series, per David
- Add recovery information for a mount failure due to patch 1 to the
cover letter.
- Link to v1: https://patch.msgid.link/20260907-btrfs-remove-v1-space-cache-v1-0-5f9a5ba352a7@xxxxxxxxxxxx
---
Tal Zussman (18):
btrfs: update the inode item when removing a free space inode
btrfs: stop enabling the v1 space cache from the on-disk state
btrfs: remove the v1 space cache writeout from the transaction commit
btrfs: remove the free space cache endio workqueue
btrfs: remove the v1 space cache write path
btrfs: rename cache_write_mutex to dirty_bgs_update_mutex
btrfs: drop the transaction handle from the prealloc helpers
btrfs: remove the v1 space cache load path
btrfs: remove btrfs_disk_cache_state
btrfs: remove the SPACE_CACHE mount option flag
btrfs: replace btrfs_set_free_space_cache_v1_active() with a cleanup helper
btrfs: remove the free space cache trimming ranges
btrfs: remove BTRFS_RESERVE_FLUSH_FREE_SPACE_INODE
btrfs: remove the free space inode ordered extent special cases
btrfs: remove the free space inode special cases from the COW paths
btrfs: stop special-casing free space inodes in the delalloc accounting
btrfs: stop reading free space inodes from the commit root
btrfs: remove TRANS_JOIN_NOLOCK
fs/btrfs/block-group.c | 497 ++-----------
fs/btrfs/block-group.h | 14 -
fs/btrfs/btrfs_inode.h | 6 -
fs/btrfs/delalloc-space.c | 13 +-
fs/btrfs/disk-io.c | 81 +--
fs/btrfs/file-item.c | 11 -
fs/btrfs/free-space-cache.c | 1670 +++++--------------------------------------
fs/btrfs/free-space-cache.h | 29 +-
fs/btrfs/fs.h | 2 -
fs/btrfs/inode.c | 157 +---
fs/btrfs/ordered-data.c | 27 +-
fs/btrfs/relocation.c | 2 +-
fs/btrfs/space-info.c | 2 -
fs/btrfs/space-info.h | 4 -
fs/btrfs/super.c | 48 +-
fs/btrfs/transaction.c | 62 +-
fs/btrfs/transaction.h | 27 +-
fs/btrfs/zoned.c | 9 -
18 files changed, 304 insertions(+), 2357 deletions(-)
---
base-commit: a5c77fde6730d32128ca69fd0c4e2b80f6012c35
change-id: 20260906-btrfs-remove-v1-space-cache-45cf57c957a2
Best regards,
--
Tal Zussman <tz2294@xxxxxxxxxxxx>