Skip to content

Test misc-next (regular, SELF) - #1629

Open
kdave wants to merge 10000 commits into
btrfs:ci-kvmfrom
kdave:misc-next
Open

kdave wants to merge 10000 commits into
btrfs:ci-kvmfrom
kdave:misc-next

Conversation

@kdave

@kdave kdave commented Apr 17, 2026

Copy link
Copy Markdown
Member

No description provided.

@kdave
kdave force-pushed the misc-next branch 8 times, most recently from a464848 to 8f84140 Compare April 27, 2026 14:35
@kdave
kdave force-pushed the misc-next branch 2 times, most recently from d93f97d to 7d5a51d Compare April 29, 2026 14:08
@kdave
kdave force-pushed the misc-next branch 2 times, most recently from 14fb724 to d39211d Compare May 12, 2026 15:26
@kdave
kdave force-pushed the misc-next branch 2 times, most recently from 8c55fe0 to 2fddc74 Compare May 16, 2026 01:02
@kdave
kdave force-pushed the misc-next branch 10 times, most recently from 014f22d to 6b43c97 Compare May 29, 2026 00:01
@kdave
kdave force-pushed the misc-next branch 4 times, most recently from 7263914 to 5342ffb Compare June 8, 2026 13:54
Tal Zussman and others added 30 commits October 16, 2026 19:06
Since commit 545e560 ("btrfs: disable v1 space cache") the mount
options can no longer request the v1 space cache, but a filesystem with
an active v1 cache and no free space tree still enables it from
cache_generation, and remount does the same. Drop both, so SPACE_CACHE
can never be set.

btrfs_start_pre_rw_mount() then sees the on-disk cache as active but
unwanted and cleans it up, as -o nospace_cache does today. That covers
the read-only to read-write remount as well, so drop the toggle in
btrfs_remount_cleanup(), which would otherwise start a transaction on
remounts of a read-only filesystem with an old cache.

When a remount that isn't read-only to read-write asks to change the
free space tree, btrfs_reconfigure() warns and keeps the on-disk state,
but the fixup that resets the options only ran for a filesystem with a
free space tree or an active v1 cache. On one with neither, a requested
FREE_SPACE_TREE stayed set and the next read-write remount created the
tree. Clear it whenever the tree is not on disk, which also covers a v1
filesystem once its cache has been cleaned up.

The cleanup is now unconditional, and the first read-write mount fails
if it fails, as it did with -o nospace_cache. This also lets an old
filesystem mount without options when the page size is larger than the
sector size, which btrfs_check_features() rejected once SPACE_CACHE was
set from the superblock.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Nothing sets SPACE_CACHE anymore, so the dirty block group writers never
have a cache to write out or wait for. Remove cache_save_setup(),
btrfs_setup_space_cache(), the io_list handling, the io_bgs list and
BTRFS_TRANS_CACHE_ENOSPC, and the abort-time cleanup of in-flight cache
IO.

The -ENOENT retry in btrfs_write_dirty_block_groups() handled a free
space endio worker creating a block group during the commit critical
section, so drop it too.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inodes are no longer written to, so nothing queues ordered
extent completion on endio_freespace_worker. Remove it and always use
endio_write_workers in btrfs_queue_ordered_fn().

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Nothing writes out a v1 space cache any more. Remove the writers and
their io_ctl helpers, along with create_free_space_inode() and
btrfs_prealloc_file_range_trans(), whose only user was the cache inode
creation. The io_list and io_ctl block group fields were only used by
the writers, so remove them too.

btrfs_truncate_free_space_cache() only needed the block group to wait
for and clear in-flight cache IO, so drop that parameter.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
The v1 space cache writeout is gone, but the mutex is still needed. It
keeps btrfs_remove_block_group() from deleting a block group item while
btrfs_start_dirty_block_groups() is updating it outside the commit
critical section.

Rename it to reflect what it protects, and update the comments around
the dirty block group writeout that still refer to the space cache.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
The v1 space cache created its inode during the transaction commit, and
btrfs_prealloc_file_range_trans() existed so that preallocation could
reuse the open handle. It was the only caller passing a transaction, so
__btrfs_prealloc_file_range() and insert_prealloc_file_extent() now
always start their own. Fold the wrapper into
btrfs_prealloc_file_range() and drop the parameter.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Nothing writes a v1 space cache any more, and since commit 545e560
("btrfs: disable v1 space cache") the mount option can't be enabled to
read one either. Remove load_free_space_cache(), its io_ctl helpers and
struct btrfs_io_ctl. Drop the gfp constraint on the inode mapping as
well, it only covered the cache's page cache allocations.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
With neither the writer nor the loader left, nothing acts on
disk_cache_state. Remove it, the need_clear handling when reading block
groups, and the enum. While at it, drop the unused cache_generation
field from struct btrfs_block_group.

lookup_free_space_inode() converted old style space inodes by clearing
disk_cache_state so the cache would be rewritten with the new inode
flags. Without that it only sets flags on the in-memory inode, which
every remaining caller truncates or deletes right after, so drop the
conversion too.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Nothing sets BTRFS_MOUNT_SPACE_CACHE anymore, so every test of it is
false. Remove the flag, the checks rejecting the v1 cache on zoned
filesystems and for sector sizes other than the page size, and the
deprecation warning. Show a read-only filesystem that still has an old
cache as nospace_cache, since that's what's in effect. space_cache and
space_cache=v1 keep falling back to no space cache with a warning.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
…helper

The only caller passes active = false. Turn it into
btrfs_cleanup_free_space_cache_v1() and fold the block group loop into
it.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
cache_writeout_mutex and trimming_ranges let the v1 cache writer see
ranges that were unlinked from the free space tree while being
discarded. Nothing consumes the list anymore, and the tree itself is
protected by tree_lock, so remove them.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inodes no longer reserve data or delalloc space, as nothing
writes to them. Remove the flush mode and the special cases that
selected it.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inodes never have ordered extents anymore. Drop the lockdep
exceptions for them and btrfs_join_transaction_spacecache(), which was
only used to finish their ordered extents during a commit.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inodes are never written anymore, so drop the special cases
for them in cow_file_range(), fallback_to_cow(),
can_nocow_file_extent() and btrfs_finish_one_ordered().

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inodes never have delalloc or outstanding extents any more,
so they don't need to be kept off the root's delalloc inode list, out of
the outstanding extents tracepoint, or exempt from the delalloc metadata
release, which skipped the tree root since free space inodes are its
only inodes with data.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
Free space inode data was only read when loading the v1 cache, which is
gone, so btrfs_get_extent() and btrfs_lookup_bio_sums() no longer need
to search the commit root for them.

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
btrfs_join_transaction_spacecache() was the only user of
TRANS_JOIN_NOLOCK and is gone, so remove the join type, its entries in
the blocked types table, and the special cases in join_transaction() and
start_transaction().

Assisted-by: LLM
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
The member btrfs_chunk_map::stripe_size sounds very similar to
btrfs_chunk::stripe_len, but they have very different meanings.

btrfs_chunk_map::stripe_size is in fact the device extent size for the
chunk. E.g. a 2GiB RAID0 chunk with 2 stripes,
btrfs_chunk_map::stripe_size will be 1GiB (2GiB / 2).

But btrfs_chunk::stripe_len is the stripe length that striping profiles
should follow, and the value is now fixed to 64KiB.
E.g. for a 2GiB RAID0 chunk with 2 stripes, every write will be split
into 64KiB stripes, and then distributed across the 2 devices.

To avoid confusion, rename btrfs_chunk_map::stripe_size to
dev_extent_size.

And since we're here, also rename the helper btrfs_calc_stripe_length()
to btrfs_calc_dev_extent_size().

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Rename the "stripe_size" used inside volumes.c by:

- local variable in alloc_virtual_chunk()
- alloc_chunk_ctl::stripe_size
  All rename to "dev_extent_size".

- alloc_chunk_ctl::max_stripe_size
  Rename to "dev_extent_max" as there is already a "dev_extent_min".

- decide_stripe_size*() functions
  Rename to decide_dev_extent_size*().

This further reduces the confusion between "stripe_size" and
"stripe_len".

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
During read_one_chunk() we can hit an existing chunk map.

There are several situations that this can happen:

- System chunk maps
  This is the most common case, where the system chunks are added from
  super block during bootstrap.

  But in that case, the system chunks in the super block should match
  the one in the chunk tree, if not there is definitely something wrong.

- Overlapping chunk maps
  This is rare, but potentially malicious.

  Crafted images or even some bitflips in the chunk tree can lead to
  this.
  In that case we should reject such cases.

To detect and reject those cases:

- Introduce a new helper, is_same_chunk_map()
  This checks most important members, so we can detect such problem
  without fully checking the stripes.

  If the helper returns false, then we output an error message and
  reject the mount.

- Use the full chunk map range for btrfs_find_chunk_map()
  The current search range is [@logical, @logical], which is only one
  bytenr in length.

  If we have the following case, btrfs_find_chunk_map() returns NULL but
  we still have an overlapping chunk map:

                   Logical
                   |<--- New chunk map --->|
                            |<--- Existing chunk map --->|

  Using the full range to do the search would return the existing chunk
  map and get the new one rejected.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Since commit 3eaf5f0 ("btrfs: extract inlined creation into a
dedicated delalloc helper"), even for inlined compressed extents the cb
range will be exact one block, aka [0, sector).

And several attempts to bring back the old compression range [0, i_size]
all failed with extra races against i_size.

So I think the behavior will stay. With that said, we can further
simplify the lzo compression path.
Since the range is always aligned to block size, and lzo compression is
already done block by block, there is no reason to handle sub-block
sized range.

We can safely remove the @sectorsize_mask, @sector_off and @in_len
variables, and always use @sectorsize as input length for each
compression iteration.

Finally add two ASSERT()s to make sure the range passed into
btrfs_compress_bio() is always block aligned.

Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
In init_scrub_stripe() we are allocating a stripe's buffer with GFP_NOFS
but we can use GFP_KERNEL instead since we are not holding a transaction
handle or any locks that could cause a deadlock if GFP_KERNEL triggers a
transaction commit.

So switch to GFP_KERNEL. We are also doing GFP_KERNEL for the allocation
of stripe->csums just a few lines below.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
…s finishing

When scrub finishes, it does a wakeup on the fs_info->scrub_pause_wait
wait queue and then sets dev->scrub_sctx to NULL. On the other hand the
scrub cancel code (btrfs_scrub_cancel_dev()) waits on that wait queue
for dev->scrub_sctx to be NULL. So this means if btrfs_scrub_cancel_dev()
is called right when scrub is finishing and sees the wakeup before the
NULL is assigned to dev->scrub_sctx by btrfs_scrub_dev(), it hangs.

Fix this by doing the wakeup in btrfs_scrub_dev() after setting
dev->scrub_sctx to NULL.

Fixes: a2de733 ("btrfs: scrub")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
It's not used since commit 001e3fc ("btrfs: scrub: remove
scrub_block and scrub_sector structures"), so remove it.

Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
…s ioctl

If the scrub progress ioctl is called when replace is about to finish, we
have a race that can result in a use-after-free of the scrub context:

1) A scrub is finishing and is at btrfs_scrub_dev();

2) A concurrent task called the scrub progress ioctl and is in
   btrfs_scrub_progress(), where it takes the device_list_mutex and grabs
   the device. Then it starts using the device's scrub context (for a
   memcpy operation);

3) While the scrub progress ioctl task is running, the scrub task sets
   the device's scrub_ctx to NULL (acquiring fs_info->scrub_lock) and
   then calls scrub_put_ctx() against the scrub context, dropping the
   last reference and freeing the memory - while the scrub progress ioctl
   task is still using it, resulting in a use-after-free.

Fix this by changing btrfs_scrub_progress() to take fs_info->scrub_lock
before using the scrub context.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
The scrub progress ioctl is copying the scrub progress stats without
acquiring the spinlock that protects it and a concurrent scrub can be
updating the stats at the same time which can lead to load tearing
issues. So take the spinlock when copying the progress stats.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Commit 6ded22c ("btrfs: reduce div64 calls by limiting the number
of stripes of a chunk to u32") introduced a chunk size limit check, but
it is using a wrong result in the comment:

  U32_MAX << BTRFS_STRIPE_LEN_SHIFT results 256T, not 256G.

Instead of calculating the size limit, using an immediate number
(SZ_256G).

This has the following benefit:

- Still large enough for future expansion
  Although the check is 1024 times more strict, I don't think we will
  allow 256G chunk anytime soon.

  And we have higher chance (10 more bits) to catch a bitflip in the
  high bits.

- Much harder to diverge from the comment
  We don't need to calculate the number anymore.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
When deleting a subvolume by ID, btrfs_ioctl_snap_destroy() first
resolves the requested ID to a name, then looks up that name again
under the parent directory lock.

A concurrent rename can change which subvolume is associated with
the name between these operations. Since the deletion path does not
verify the ID of the resolved subvolume, it can delete a different
subvolume while leaving the requested one intact.

This was reproduced by repeatedly exchanging the names of two
subvolumes using renameat2(RENAME_EXCHANGE) while deleting one of
them by ID. The wrong subvolume was deleted in 9 out of 14 independent
tests.

Fix this by checking that the resolved subvolume ID matches the
requested ID while holding the parent directory lock. Return -EAGAIN
on a mismatch so that userspace can retry the operation instead of
being told that the requested subvolume does not exist.

Fixes: 949964c ("btrfs: add new BTRFS_IOC_SNAP_DESTROY_V2 ioctl")
Cc: stable@vger.kernel.org
Signed-off-by: guolingxing <guolingxing@tju.edu.cn>
Signed-off-by: David Sterba <dsterba@suse.com>
btrfs_ioctl_defrag() checks MAY_WRITE against nop_mnt_idmap, so on an
idmapped mount the owner comparison uses the caller's fsuid against the
raw on-disk uid and the ioctl fails with -EPERM even for the file's
owner.  Pass the mount idmap down so defrag works on idmapped mounts.

The check, added in 616d374 ("btrfs: allow defrag on a file opened
read-only that has rw permissions"), is not a privilege gate.  It only
tests whether the file could have been opened for writing, and a user
who owns the file on the idmapped mount can already open it O_RDWR,
write() to it or fallocate() it.  Defragmenting a regular file only
rearranges the caller's own extents; there is nothing it can rewrite
that the caller could not rewrite anyway.  Whole-subvolume defrag on a
directory keeps its capable(CAP_SYS_ADMIN) requirement, and the
!capable() guard around this check is left as is.

FIDEDUPERANGE already works this way for unprivileged callers:
may_dedupe_file() in fs/remap_range.c compares the inode owner through
file_mnt_idmap(file) and falls back to inode_permission() with the same
idmap, and dedupe can rewrite one file's extents from another file's
contents, which is a stronger operation than defrag.

On regular mounts file_mnt_idmap() is nop_mnt_idmap and nothing
changes.

Reviewed-by: Seth Forshee <sforshee@kernel.org>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
Signed-off-by: David Sterba <dsterba@suse.com>
Any commits after this one are for testing and evaluation only.

Signed-off-by: David Sterba <dsterba@suse.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.