[PATCH 00/15] btrfs: remove the v1 space cache

Tal Zussman posted 15 patches 2 weeks, 3 days ago
There is a newer version of this series
fs/btrfs/block-group.c      |  461 +------------
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 | 1603 ++++---------------------------------------
fs/btrfs/free-space-cache.h |   29 +-
fs/btrfs/fs.h               |    2 -
fs/btrfs/inode.c            |  149 +---
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      |   37 +-
fs/btrfs/transaction.h      |   27 -
fs/btrfs/zoned.c            |    9 -
18 files changed, 226 insertions(+), 2299 deletions(-)
[PATCH 00/15] btrfs: remove the v1 space cache
Posted by Tal Zussman 2 weeks, 3 days ago
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 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. Patches 2-5
remove the write path, 6 and 7 the load path and disk_cache_state, and
8 and 9 the SPACE_CACHE flag and the unused half of the cleanup helper.
Patches 10-15 remove the trimming ranges and the free space inode
special cases in the write path, which only the v1 writer used.

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 btrfs/for-next.

[1] https://lore.kernel.org/linux-btrfs/e1dd5a75-9a67-4bc6-b8d8-bfff79b5b907@suse.com/

---
Tal Zussman (15):
      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: 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

 fs/btrfs/block-group.c      |  461 +------------
 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 | 1603 ++++---------------------------------------
 fs/btrfs/free-space-cache.h |   29 +-
 fs/btrfs/fs.h               |    2 -
 fs/btrfs/inode.c            |  149 +---
 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      |   37 +-
 fs/btrfs/transaction.h      |   27 -
 fs/btrfs/zoned.c            |    9 -
 18 files changed, 226 insertions(+), 2299 deletions(-)
---
base-commit: 69b26c13e520480d1869171e2c2b8a59f0c857ec
change-id: 20260906-btrfs-remove-v1-space-cache-45cf57c957a2

Best regards,
--  
Tal Zussman <tz2294@columbia.edu>
Re: [PATCH 00/15] btrfs: remove the v1 space cache
Posted by David Sterba 2 weeks, 2 days ago
On Mon, Sep 07, 2026 at 09:19:15PM -0400, Tal Zussman wrote:
> 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 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.

In case it fails there are 2 ways how to fix it:

- convert to free space tree during mount (the recommended conversion
  from v1 to v2) but it could fail for the same reason

- on unmounted filesystem do 'btrfs rescue clear-space-cache v1'

> Patches 2-5
> remove the write path, 6 and 7 the load path and disk_cache_state, and
> 8 and 9 the SPACE_CACHE flag and the unused half of the cleanup helper.
> Patches 10-15 remove the trimming ranges and the free space inode
> special cases in the write path, which only the v1 writer used.

The piecemeal removal is good, makes it clear what's still needed, as
listed below.

> 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.

The sperblock::space_cache will remain unused and the only valid value
is 0. Repurposing it in the future is possible but we need a long period
in between.

The points listed above for the code that will be still needed seem
minimal. It could be removed eventually leaving only the unmounted
clearing.

I'll add the series as topic branch to linux-next. The mentioned change
to tranaction NOJOIN is simple and no-op in the code so it'll get
updated for the final merge.
Re: [PATCH 00/15] btrfs: remove the v1 space cache
Posted by Tal Zussman 2 weeks, 2 days ago
On 9/9/26 4:08 AM, David Sterba wrote:
> On Mon, Sep 07, 2026 at 09:19:15PM -0400, Tal Zussman wrote:
>> 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 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.
> 
> In case it fails there are 2 ways how to fix it:
> 
> - convert to free space tree during mount (the recommended conversion
>    from v1 to v2) but it could fail for the same reason
> 
> - on unmounted filesystem do 'btrfs rescue clear-space-cache v1'
> 

Thanks, I'll add this to the cover letter.

>> Patches 2-5
>> remove the write path, 6 and 7 the load path and disk_cache_state, and
>> 8 and 9 the SPACE_CACHE flag and the unused half of the cleanup helper.
>> Patches 10-15 remove the trimming ranges and the free space inode
>> special cases in the write path, which only the v1 writer used.
> 
> The piecemeal removal is good, makes it clear what's still needed, as
> listed below.
> 
>> 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.
> 
> The sperblock::space_cache will remain unused and the only valid value
> is 0. Repurposing it in the future is possible but we need a long period
> in between.
> 
> The points listed above for the code that will be still needed seem
> minimal. It could be removed eventually leaving only the unmounted
> clearing.
> 
> I'll add the series as topic branch to linux-next. The mentioned change
> to tranaction NOJOIN is simple and no-op in the code so it'll get
> updated for the final merge.
> 

Great, thank you! I'll send a v2 with the transaction split in a couple
days.