Commit graph

1,464,795 commits

Author SHA1 Message Date
Qu Wenruo
4cbafa2ff3 btrfs: remove btrfs_chunk_map::io_(align|width) members
Those two members are read from on-disk metadata, but never utilized.
And for new chunks we always set those members to BTRFS_STRIPE_LEN
anyway.

Thus there is no need to keep them inside btrfs_chunk_map.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
Qu Wenruo
690c2accac btrfs: make sure EXTENT_BUFFER_READING is cleared under refs_lock
[FALSE ALERTS]
There is a bug report that the warning inside
invalidate_and_check_btree_folios() got triggered during btrfs/298:

 BTRFS info (device sdd): first mount of filesystem f9bf732a-a19b-44b9-99a7-614ddff168e2
 BTRFS info (device sdd): using crc32c checksum algorithm
 BTRFS error (device sdd): failed to find fsid cb2fdb42-b638-4f2f-badd-4127467ba674 when attempting to open seed devices
 BTRFS error (device sdd): failed to read chunk tree: -2
 ------------[ cut here ]------------
 WARNING: disk-io.c:3342 at invalidate_and_check_btree_folios+0x260/0x3c0 [btrfs], CPU#4: mount/125993
 CPU: 4 UID: 0 PID: 125993 Comm: mount Tainted: G        W  OE       7.1.0-rc7-custom+ #1 PREEMPT(full)
 Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20250812-19.fc42 08/12/2025
 Call trace:
  invalidate_and_check_btree_folios+0x260/0x3c0 [btrfs] (P)
  open_ctree+0x1f50/0x23b0 [btrfs]
  btrfs_get_tree+0x89c/0xc48 [btrfs]
  vfs_get_tree+0x30/0x110
  vfs_cmd_create+0x58/0xe8
  __arm64_sys_fsconfig+0x39c/0x518
  invoke_syscall.constprop.0+0x48/0x120
  el0_svc_common.constprop.0+0x40/0xe8
  do_el0_svc+0x24/0x38
  el0_svc+0x50/0x310
  el0t_64_sync_handler+0xa0/0xe8
  el0t_64_sync+0x198/0x1a0
 ---[ end trace 0000000000000000 ]---
 BTRFS warning (device sdd): unable to release extent buffer 365985792 owner 3 gen 17 refs 3 flags 0x5

[CAUSE]
In that invalidate_and_check_btree_folios() we wait for the eb to finish
its read, then check if it's only held by us and the btree inode.

If not, then do a warning as it may be still held, and could cause
problems.

But there is a small window where the check can lead to false alerts:

    Thread A (Read endio)         |        Thread B (Unmount)
----------------------------------+-------------------------------------
 end_bbio_meta_read()             |
 | The eb has one extra ref held  |
 | by the reader, and has         |
 | EXTENT_BUFFER_READING flag set | invalidate_and_check_btree_folios()
 |                                | |
 |- clear_extent_buffer_reading() | |
 |                                | |- wait_on_bit_io();
 |                                | |  The EXTENT_BUFFER_READING flag is
 |                                | |  cleared
 |                                | |- if (refcount_read(eb->refs) > 2)
 |                                |    The eb is held by the read, us
 |                                |    and btree inode, thus it
 |                                |    will trigger the warning
 |- free_extent_buffer()          |

[FIX]
Introduce a helper, free_extent_buffer_clear_reading().

If the new parameter, @clear_reading, is set, we will hold the spinlock
at the beginning of free_extent_buffer_clear_reading() to make sure the
EXTENT_BUFFER_READING flag is cleared inside the same critical section
of decreasing refs.

Now free_extent_buffer() will just call
free_extent_buffer_clear_reading() with @clear_reading set to false, so
no behavior change.

But for end_bbio_meta_read(), it will not clear_extent_buffer_reading()
directly, but pass @clear_reading as true.

Then inside invalidate_and_check_btree_folios(), hold the refs_lock
before reading refs.
So that we eliminate the race window completely.

Reported-by: Su Yue <glass.su@suse.com>
Link: https://lore.kernel.org/linux-btrfs/DC0C775E-13B3-47D9-9AB2-895BB11C029D@suse.com/
Fixes: 83f7e52b7e ("btrfs: warn about extent buffer that can not be released")
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
Boris Burkov
5376c9db45 btrfs: write-protect folios during data writeback
commit 095be159f3 ("btrfs: unify folio dirty flag clearing") replaced
the folio_clear_dirty_for_io() call in extent_write_cache_pages() with a
plain folio_test_dirty() check. Besides clearing the dirty flag,
folio_clear_dirty_for_io() also calls folio_mkclean(), which write-protects
the shared mmap PTEs mapping the folio. Note that we still do call
folio_clear_dirty_for_io() later in submit_one_sector() when we clear
dirty on the last sector of the folio (the only sector for non-subpage
cases). But we lost this early call in extent_write_cache_pages().

Without the extra write-protection, a process with the file mmap-ed can
modify a sector while it is being used by writeback in a way that
expects a stable folio (checksumming, compressing, copying, etc...)
without faulting, which manifests as a handful of concrete bugs.

1. For large folios or subpage sectorsize, it is possible to submit a bio
which does not cover the whole folio. When this happens, we will have a
bio in flight for a folio that we have *not* called
folio_clear_dirty_for_io() on. If a task with an existing mmap-ed PTE
writes (without faulting..) in this window, it can result in
corruptions. If the write arrives while the checksumming or writing itself
is underway, this can result in an invalid checksum and later corruption
reports on read. If the write arrives after checksumming/writing is done
but before the last sector dirty is cleared, then the write is present
in page cache but doesn't affect the dirty tracking and will be lost
when the folio is fully finished being submitted and the dirty bit
is cleared. This results in losing the write even if fsync() is called.

2. For zoned submissions which are done in batch separate from the main
extent_writepage() loop, we also risk csum violations for those
submissions. Zoned writes are clamped to max_zone_append_size and are
not aligned with folios, so a submission can span two folios. The first
folio being processed in extent_write_cache_pages() will call
extent_write_locked_range() which will submit the partial range of the
next folio, while the rest of that folio could still be dirty. So
clearing dirty on the submitted sectors doesn't call
folio_clear_dirty_for_io() and we have the same issue. Since
extent_write_cache_pages() skips these batch submitted folios (they are
already marked for writeback from submission by the preceding folio), we
must add the extra write protection in lock_delalloc_folios().

3. For inline extents this will subtly risk losing writes that happen
after/while we copy the inline extent but before we clear dirty on
the folio.

4. For folios spanning EOF, mmap could tamper with the zeroed bytes past
EOF and cause them to be persisted where future faults would improperly
see them instead of zeros.

5. Finally, for compressed extents, we risk modifying the folios while we
work on compressing them which will result in corrupted compressed data.
Specifically, in run_delalloc_compressed() we queue up work to do
compress_file_range() in BTRFS_COMPRESSION_CHUNK_SIZE (512K) chunks which
will call btrfs_folio_clamp_clear_dirty() on the range. For non-subpage,
this will always clear the whole folio, safely. For subpage, we risk a
partial clear here as well. In particular, imagine a 2M folio broken up
into 512K chunks of work which might start compression work on one chunk
before all the chunks compress_file_range() workers have gotten far
enough to finish clearing all the dirty bitmaps of the folio and getting
to folio_clear_dirty_for_io(). Large folios on the edges of submission
ranges are similarly at risk to be only partly cleared.
This particular gap was introduced by a second patch in the same series:
commit a4ef54dbb5 ("btrfs: make extent_range_clear_dirty_for_io() to handle sector size < page size cases")

We cannot simply restore the call to folio_clear_dirty_for_io() because
that also drops the dirty flag off the folio which violates invariants
introduced for large folios by
commit 334509ce9d07 ("btrfs: use dirty flag to check if an ordered extent needs to be truncated")
and results in failing to invalidate clean folios past i_size, resulting
in deadlocks.

Therefore, to fix it, leave the existing semantics w.r.t. the folio's
dirty flag (to preserve the correct invalidate behavior) but ensure that
the other aspect of folio_clear_dirty_for_io(), folio_mkclean(), is run
on the folio when we lock it for writeback.

Finally, to help prevent similar regressions in the future, add a debug
warning that triggers at the known corruption sites if we have failed to
write protect the folio.

Assisted-by: LLM (debug, reproduce, research fix, review patch)
Fixes: 095be159f3 ("btrfs: unify folio dirty flag clearing")
Fixes: a4ef54dbb5 ("btrfs: make extent_range_clear_dirty_for_io() to handle sector size < page size cases")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
Qu Wenruo
108cc87339 btrfs: fix a lockdep caused by path resolution during device scan
[BUG]
There is a lockdep report related to device scan:

======================================================
WARNING: possible circular locking dependency detected
7.2.0-20260712.rc2.git0.e3321fa3034d.300.fc44.s390x+debug #1 Not tainted
------------------------------------------------------
(udev-worker)/1653 is trying to acquire lock:
0000006919232220 (&type->i_mutex_dir_key#2){++++}-{3:3}, at: lookup_slow+0x3e/0x70
but task is already holding lock:
00000069238564d8 (&fs_devs->device_list_mutex){+.+.}-{3:3}, at: device_list_add.constprop.0+0x148/0xc60
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #5 (&fs_devs->device_list_mutex){+.+.}-{3:3}:
       lock_acquire+0x150/0x3f0
       __mutex_lock+0xba/0xdc0
       mutex_lock_nested+0x32/0x40
       write_all_supers+0x7a/0x670
       btrfs_sync_log+0xae6/0xdd0
       btrfs_sync_file+0x4fa/0x7a0
       __s390x_sys_fsync+0x52/0xa0
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
-> #4 (&fs_info->tree_log_mutex){+.+.}-{3:3}:
       lock_acquire+0x150/0x3f0
       __mutex_lock+0xba/0xdc0
       mutex_lock_nested+0x32/0x40
       btrfs_sync_log+0xaba/0xdd0
       btrfs_sync_file+0x4fa/0x7a0
       __s390x_sys_fsync+0x52/0xa0
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
-> #3 (btrfs_trans_num_extwriters){.+.+}-{0:0}:
       lock_acquire+0x150/0x3f0
       join_transaction+0x108/0x680
       start_transaction+0x21a/0x660
       btrfs_join_transaction+0x32/0x40
       btrfs_dirty_inode+0x52/0xf0
       touch_atime+0x90/0xc0
       filemap_read+0x446/0x450
       vfs_read+0x208/0x370
       ksys_read+0x88/0x120
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
-> #2 (btrfs_trans_num_writers){.+.+}-{0:0}:
       reacquire_held_locks+0x14c/0x240
       __lock_release.isra.0+0xd8/0x380
       lock_release+0xf6/0x270
       percpu_up_read+0x28/0xf0
       __btrfs_end_transaction+0x178/0x1f0
       btrfs_dirty_inode+0x82/0xf0
       touch_atime+0x90/0xc0
       btrfs_file_mmap_prepare+0x8c/0xa0
       __mmap_region+0x214/0x780
       mmap_region+0x108/0x160
       do_mmap+0x402/0x5a0
       vm_mmap_pgoff+0x156/0x230
       ksys_mmap_pgoff+0x17e/0x220
       __s390x_sys_old_mmap+0xa8/0x140
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
-> #1 (&mm->mmap_lock){++++}-{3:3}:
       lock_acquire+0x150/0x3f0
       __might_fault+0x7a/0xa0
       filldir64+0x11c/0x210
       offset_readdir+0x92/0x200
       iterate_dir+0xcc/0x2d0
       __do_sys_getdents64+0x7a/0x130
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
-> #0 (&type->i_mutex_dir_key#2){++++}-{3:3}:
       check_prev_add+0x160/0xf40
       __lock_acquire+0x12aa/0x15a0
       lock_acquire+0x150/0x3f0
       down_read+0x5a/0x280
       lookup_slow+0x3e/0x70
       path_lookupat+0x1f0/0x370
       filename_lookup+0xce/0x1f0
       kern_path+0x48/0x70
       is_same_device+0x146/0x300
       device_list_add.constprop.0+0x1be/0xc60
       btrfs_scan_one_device+0x13a/0x2f0
       btrfs_control_ioctl+0x110/0x1e0
       __s390x_sys_ioctl+0xfa/0x130
       __do_syscall+0x172/0x750
       system_call+0x72/0x90
other info that might help us debug this:
Chain exists of:
  &type->i_mutex_dir_key#2 --> &fs_info->tree_log_mutex --> &fs_devs->device_list_mutex
 Possible unsafe locking scenario:
       CPU0                    CPU1
       ----                    ----
  lock(&fs_devs->device_list_mutex);
                               lock(&fs_info->tree_log_mutex);
                               lock(&fs_devs->device_list_mutex);
  rlock(&type->i_mutex_dir_key#2);
 *** DEADLOCK ***
2 locks held by (udev-worker)/1653:
 #0: 0000016c727051c8 (uuid_mutex){+.+.}-{3:3}, at: btrfs_control_ioctl+0x102/0x1e0
 #1: 00000069238564d8 (&fs_devs->device_list_mutex){+.+.}-{3:3}, at: device_list_add.constprop.0+0x148/0xc60
stack backtrace:
CPU: 2 UID: 0 PID: 1653 Comm: (udev-worker) Not tainted 7.2.0-20260712.rc2.git0.e3321fa3034d.300.fc44.s390x+debug #1 PREEMPT
Hardware name: IBM 3931 A01 701 (LPAR)
Call Trace:
 [<0000016c70680e3e>] dump_stack_lvl+0xae/0x108
 [<0000016c7078aa44>] print_circular_bug+0x1a4/0x230
 [<0000016c7078ac5c>] check_noncircular+0x18c/0x1b0
 [<0000016c7078c030>] check_prev_add+0x160/0xf40
 [<0000016c7078fbaa>] __lock_acquire+0x12aa/0x15a0
 [<0000016c7078fff0>] lock_acquire+0x150/0x3f0
 [<0000016c7180e2fa>] down_read+0x5a/0x280
 [<0000016c70b88dde>] lookup_slow+0x3e/0x70
 [<0000016c70b8f5d0>] path_lookupat+0x1f0/0x370
 [<0000016c70b900ae>] filename_lookup+0xce/0x1f0
 [<0000016c70b90218>] kern_path+0x48/0x70
 [<0000016c70f5b4a6>] is_same_device+0x146/0x300
 [<0000016c70f67cfe>] device_list_add.constprop.0+0x1be/0xc60
 [<0000016c70f688da>] btrfs_scan_one_device+0x13a/0x2f0
 [<0000016c70ed9cb0>] btrfs_control_ioctl+0x110/0x1e0
 [<0000016c70b97d0a>] __s390x_sys_ioctl+0xfa/0x130
 [<0000016c718004d2>] __do_syscall+0x172/0x750
 [<0000016c718155d2>] system_call+0x72/0x90

[CAUSE]
Btrfs device scan will call is_same_device() with device_list_mutex
held. But is_same_device() will call kern_path() which will do path
resolution and lock the inode.

So device scan has the following lock sequence:

 mutex_lock(device_list_mutex) from device_list_add()
   |
   v
 inode_lock_shared() from lookup_slow() during kern_path().

Meanwhile another thread is fsyncing, which has the following
lock sequence:

 inode_lock() from btrfs_inode_lock() inside btrfs_direct_write()
   |
   v
 mutex_lock(tree_log_mutex() from btrfs_sync_log(), which is further
 triggered from
 iomap_dio_complete()->generic_write_sync()->btrfs_sync_file().
   |
   v
 mutex_lock(device_list_mutex) from write_all_supers() inside
 btrfs_sync_log().

So the device scan has a reversed lock sequence, compared to the fsync
one, this means we can have the following deadlock:

          Device scan                   |           Fsync
----------------------------------------+--------------------------------
 device_list_mutex locked               |
                                        |   inode locked
					|   try to lock device_list_mutex
 try to lock inode                      |

[FIX]
Instead of a full path lookup, use dev_t to determine if two device
paths are pointing to the same block device.

Inside kernel dev_t is going to uniquely determine a block device, and
the device path lookup is already done by lookup_bdev(), which is done
without device_list_mutex held, thus no reversed locking sequence.

Reported-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Link: https://lore.kernel.org/linux-btrfs/5a9d9847-4ae6-43c4-afdc-6e5fa51d6117@linux.ibm.com/
Fixes: 2e8b6bc0ab ("btrfs: avoid unnecessary device path update for the same device")
Tested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
Sun YangKai
c5ac19b985 btrfs: change block group reclaim_mark to bool
The reclaim_mark field in struct btrfs_block_group was a u64 that was
incremented when marking block groups for reclaim during sweeping, but
the actual counter value was never used - only the zero/non-zero state
mattered for determining if a block group needed reclaim.

Convert it to a bool to properly reflect its usage and reduce memory
footprint by 8 bytes. Update assignments to use true/false instead of
increment and zero.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Sun YangKai <sunk67188@gmail.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
David Sterba
77038da5a9 btrfs: sink idmap parameter to __btrfs_ioctl_snap_create()
The 'idmap' parameter is derived from 'file' that we also pass to
__btrfs_ioctl_snap_create(), assign it inside the function.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:17 +02:00
Qu Wenruo
6de9a91f87 btrfs: use kvmalloc() for stripe buffer of scrub_stripe
Currently we're using scrub_stripe::folios[] to store all contents of a
stripe.

This means we need all the extra work to handle things like sub-page
cases, and also require larger folios to handle bs > ps cases.

On the other hand, it's not hard to allocate a 64K large folio to cover
the full stripe, getting rid of the cross-page handling.

Furthermore, even if that large folio allocation failed, we can still
use vmalloc() to allocate a virtually contiguous space and still get rid
of cross-page handling.

This patch will go with kvmalloc() to allocate 64K of memory for
the stripe buffer, thus getting rid of all the complex cross-page
handling.

The following aspects can be greatly simplified:

- Checksum verification for both data and metadata
  No more per-page iteration, all in one go.

- RAID56 data caching
  Just copy the buffer into the RAID56 pages.

- No more kaddr/paddr grabbing
  For most cases the virtual address is enough for csum calculation and
  io submission.

- Bio assembly
  There is already the helper bio_add_vmalloc() to queue vmallocated
  memory into a bio.

Although it means we have something else to be concerned about:

- Bio assembly
  If the memory is vmallocated, we need to use bio_add_vmalloc()
  Otherwise use the existing bio_add_page().

- Read endio
  For vmallocated memory, we need to call
  invalidate_kernel_vmap_range().

- Scrub bbio bvec size
  Since scrub_stripe::buffer is kvmallocated, we also need to enlarge
  the scrub bbio, to be able to handle the worst case, where all 64KiB is
  allocated by discontiguous 4K physical pages.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
36c9fddcf8 btrfs: scrub: implement calc_sector_number() in a faster way
Currently calc_sector_number() is implemented by comparing the first
bvec of the bbio against all blocks inside a scrub_stripe.

This implementation is a little inefficient, and depends on how the
scrub buffer is implemented.

One of the reason implementing such complex function is that, we do not
save the original bvec_iter inside a write btrfs_bio.
Although a read bbio has btrfs_bio::saved_iter to get the original
logical bytenr, it's not implemented for write bios.

On the other hand, since commit 81cea6cd70 ("btrfs: remove
btrfs_bio::fs_info by extracting it from btrfs_bio::inode"), we always
set the btrfs_bio::file_offset as the logical bytenr for scrub, and that
member will not be modified during IO.

So this means we have a stable way to determine the logical bytenr for a
scrub bio, now calc_sector_number() is just as simple as:

	return (bbio->file_offset - stripe->logical) >> sectorsize_bits;

Since we're here, also add an ASSERT() to make sure the bbio is inside
the stripe, and change the return type to unsigned int to be extra safe.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
1462637d55 btrfs: factor out common scrub read endio into a helper
For both scrub_repair_read_endio() and scrub_read_endio(), they share
the same bitmap update and bio put.  Factor out the common code into a
helper to reduce duplication.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
ecfe11e8f4 btrfs: remove SCRUB_MAX_SECTORS_PER_BLOCK
The last user of this macro is removed in commit 001e3fc263 ("btrfs:
scrub: remove scrub_block and scrub_sector structures").

Now that macro is only utilized in an ASSERT(), which no longer makes
much sense.

Just remove it completely.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
a503aa0610 btrfs: get rid of useless label in btrfs_create_dio_extent()
There's no point in having a label where under it we do nothing but return
a variable. So remove it and directly return where we used to goto.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Shuangpeng Bai
3f950867c3 btrfs: fix extent map leak in NOCOW direct I/O write
btrfs_dio_iomap_begin() calls btrfs_get_extent(), which returns an
extent map reference that must be dropped on all exit paths.

For direct writes into a NOCOW range, btrfs_get_blocks_direct_write()
keeps using that extent map and asks btrfs_create_dio_extent() to
allocate the ordered extent. If that fails, for example because
btrfs_alloc_ordered_extent() fails, the function returns the error
without dropping the input extent map. The PREALLOC path avoided this by
dropping the input extent map before replacing it with the newly created
one.

Check the error from btrfs_create_dio_extent() before replacing the
map and drop the input extent map on failure.

Fixes: 5f9a8a51d8 ("Btrfs: add semaphore to synchronize direct IO writes with fsync")
CC: stable@vger.kernel.org
Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
ee2851074b btrfs: remove "usebackuproot" mount option
This mount option is marked deprecated since the introduction of
"rescue=" mount option group, in v5.9.

That's already a long time ago, and it should be safe to completely
remove the old "usebackuproot" mount option now.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
2fd3f6a271 btrfs: add "rescue=usebackuproot" into "rescue=all" shortcut
The mount option "rescue=all" should be a shortcut to include all
"rescue=" mount options. But unfortunately "rescue=usebackuproot" is not
included.

Include that option so "rescue=all" has a better chance to mount a
corrupted fs.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
ce5d6709eb btrfs: add "rescue=usebackuproot" into forced read-only options
According to btrfs(5) man page, all rescue options should require a
read-only mount.

But that read-only check is only introduced for newer rescue options,
not for the pre-existing "usebackuproot" one.

Furthermore, a filesystem that requires "rescue=" mount option already
means it's corrupted, even if "rescue=usebackuproot" allowed the fs to
be mounted RW, one should not trust such fs anymore until a
comprehensive btrfs-check run and proper evaluation.

Change the behavior to match the document, and since
"rescue=usebackuproot" is now a full RO mount option, it is no longer a
one-shot option, therefore remove it from btrfs_clear_oneshot_options().

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Miquel Sabaté Solà
b6890439d4 btrfs: don't pass tree_id in btrfs_search_path_in_tree()
The 'tree_id' parameter in btrfs_search_path_in_tree() was only being
used in order to fetch the root tree to be considered for the
search. For this same reason this function was also requiring a 'struct
btrfs_fs_info' parameter. This commit replaces these two parameters with
a single 'struct btrfs_root' one, which identifies from which root tree
the search should happen.

This function only has one caller, the inode lookup ioctl, which knows
how to provide the root tree for each case. In fact, if args->treeid ==
0, then we don't even have to allocate a new root tree object, and we
can reuse the one provided by the ioctl system call, thus avoiding an
extra allocation.

Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
e9b7b9d9e7 btrfs: use IOMAP_DIO_BOUNCE flag instead of falling back to buffered IO
Previously btrfs forces direct writes to fall back to buffered ones if the
inode has data checksum or the profile has duplication.

That fallback is to avoid the content being modified that the final
content may mismatch with the checksum or the other mirrors.

That brings a pretty huge performance cost, which already caused some
concern at that time.

But later upstream commit c9d114846b ("iomap: add a flag to bounce
buffer direct I/O") introduced a new method by copying the content into
new pages, and do all the operations based on the newly allocated pages.

So let btrfs to utilize the new flag for direct writes if we require
stable folios.

There is a quick benchmark, using the following fio setup:

 fio --name=randwrite --filename $mnt/foobar --ioengine=libaio --size=4G \
     --rw=randwrite --iodepth=64 --runtime=60 --time_based --direct=1 \
     --bs=$blocksize

Unit is MiB/s.

 Blocksize | Zero-copy (*) | Buffered |   Bounce
-----------+---------------+----------+-----------
        4K |          35.1 |     17.1 |      33.8
       64K |           522 |      251 |       492

*: This is done by reverting the commit 968f19c5b1 ("btrfs: always
   fallback to buffered write if the inode requires checksum")

Although with page bouncing the performance is only around 95% of
true-zero copy, it's still almost double the performance of buffered
fallback.

There will be a small change in behavior, since we're using
IOMAP_DIO_BOUNCE flag to allocate new folios, NOWAIT flag will
immediately fail.

So for true NOWAIT direct IOs, NODATASUM and RAID0/SINGLE profiles are
still required.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Qu Wenruo
ec78575dde btrfs: always wait for ordered extents to avoid OE races
[BUG]
Syzbot reported a bug that there can be conflicting OEs for the same
range:

  BTRFS critical (device loop4): panic in insert_ordered_extent:264: overlapping ordered extents, existing oe file_offset 16384 num_bytes 430080 flags 0x1089, new oe file_offset 16384 num_bytes 430080 flags 0x80 (errno=-17 Object alrea[  179.162726][ T6897] BTRFS critical (device loop4): panic in insert_ordered_extent:264: overlapping ordered extents, existing oe file_offset 16384 num_bytes 430080 flags 0x1089, new oe file_offset 16384 num_bytes 430080 flags 0x80 (errno=-17 Object already exists)
  ------------[ cut here ]------------
  kernel BUG at fs/btrfs/ordered-data.c:264!
  Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026
  RIP: 0010:btrfs_alloc_ordered_extent+0x943/0xad0
  Call Trace:
   <TASK>
   cow_file_range+0x744/0x12a0
   fallback_to_cow+0x5ea/0xa00
   run_delalloc_nocow+0x110c/0x17a0
   btrfs_run_delalloc_range+0xbe4/0x1c20
   writepage_delalloc+0x104d/0x1ba0
   btrfs_writepages+0x1667/0x28b0
   do_writepages+0x338/0x560
   filemap_fdatawrite_range+0x1f2/0x300
   btrfs_fdatawrite_range+0x54/0xf0
   btrfs_direct_write+0x6a0/0xc30
   btrfs_do_write_iter+0x329/0x790
   do_iter_readv_writev+0x624/0x8d0
   vfs_writev+0x34c/0x990
   __se_sys_pwritev2+0x17a/0x2a0
   do_syscall_64+0x174/0x580
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
   </TASK>
  ---[ end trace 0000000000000000 ]---

[CAUSE]
Since commit ff66fe6662 ("btrfs: fix incorrect buffered IO fallback
for append direct writes"), if the direct IO finished short, we will
revert the isize back to the original one, so that append writes can be
respected during the buffered fallback.

Normally we rely on lock_and_cleanup_extent_if_need() function during
buffered writeback to wait for any existing ordered extents.

But that ordered extent waiting only happens if the start_pos is inside
the isize.
Since we have reverted the isize during failed direct IO, we will not
wait for any ordered extents.

This means we can have a race where the direct IO OE is still in the
tree, finished but not yet removed, then we're inserting the OE for the
buffered write, causing the above crash.

[FIX]
Make the OE wait to be unconditional, to handle the reverted isize
situation.

And since lock_and_cleanup_extent_if_need() now either lock the
extents or return -EAGAIN, also remove the branches that handles
no-extent-locked cases, and rename it to remove the "_if_need" suffix.

The following micro benchmark shows the runtime difference for
btrfs_buffered_write(), doing `xfs_io -f -c "pwrite 0 1m"` workload,
all values are the average runtime in nano seconds.

      function runtime              |   before    |     after
 -----------------------------------+-------------+---------------
 lock_and_cleanup_extent_if_need()  |     58.2    |    183.0
 btrfs_buffered_write()             |   2115.6    |   2973.3

The overall runtime of btrfs_buffered_write() is still pretty
tiny (still less than 3 micro seconds), I'd say the extra cost is still
acceptable.

An alternative to fix this problem is to wait ordered extents during
iomap_end() where the isize revert is done.

But that solution will break nowait requirement, as if a nowait direct
IO finished short, we have to wait for the OEs unconditionally or the
next append buffered IO can still hit the same problem.

So here we have to move the wait cost to buffered write, but at least
the code is slightly more streamline.

Reported-by: syzbot+ba2afde329fc27e3f22e@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=ba2afde329fc27e3f22e
Fixes: ff66fe6662 ("btrfs: fix incorrect buffered IO fallback for append direct writes")
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
217aeb1d50 btrfs: defrag: remove pointless list_del_init() in defrag_one_cluster()
There's no need to call list_del_init() against each entry when freeing
the list, as the list is local and we are freeing the entry.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
3f66b272ff btrfs: defrag: use simple list_del() in defrag_collect_targets()
When freeing the entries from the list there is no need to initialize
the list member in an entry, since we are immediately freeing it. So use
simple list_del() instead of list_del_init().

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
d5b675c30a btrfs: defrag: use auto kfree in defrag_one_range() for folios array
Use AUTO_KFREE() for the folios array, avoiding two kfree() calls, one of
them in a very specific error path.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
28bc34d647 btrfs: defrag: use a single list for each loop in defrag_one_range()
There's no need to have one list for each loop to defrag each subrange and
then another one to free each subrange (struct defrag_target_range).
We can do it in a single loop, freeing each subrange after defragging,
plus no need to delete each subrange from the list since we immediately
free it.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:16 +02:00
Filipe Manana
0429b343f1 btrfs: fix pending delayed iputs when using autodefrag
Syzbot reported the following warning recently:

   [157.672][ T6611] BTRFS info (device loop0): turning on flush-on-commit
   [157.672][ T6611] BTRFS info (device loop0): enabling free space tree
   [157.672][ T6611] BTRFS info (device loop0): enabling auto defrag
   [157.672][ T6611] BTRFS info (device loop0): use lzo compression, level 1
   [157.672][ T6611] BTRFS info (device loop0): max_inline set to 4096
   [158.094][ T5608] BTRFS info (device loop2): last unmount of filesystem c9fe44da-de57-406a-8241-57ec7d4412cf
   [160.073][ T6656] BTRFS info (device loop0 state M): max_inline set to 4096
   [160.418][ T5611] BTRFS info (device loop0): last unmount of filesystem ab8108e1-bea5-4a9f-94c9-a3ff208d732a
   [160.432][ T6662] loop2: detected capacity change from 0 to 32768
   [160.438][ T6662] BTRFS: device fsid c9fe44da-de57-406a-8241-57ec7d4412cf devid 1 transid 8 /dev/loop2 (7:2) scanned by syz.2.74 (6662)
   [160.459][ T6662] BTRFS info (device loop2): first mount of filesystem c9fe44da-de57-406a-8241-57ec7d4412cf
   [160.459][ T6662] BTRFS info (device loop2): using crc32c checksum algorithm
   [160.634][ T1187] ------------[ cut here ]------------
   [160.634][ T1187] test_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state)
   [160.634][ T1187] WARNING: fs/btrfs/inode.c:3596 at btrfs_add_delayed_iput+0x2e3/0x340, CPU#0: kworker/u8:10/1187
   [160.634][ T1187] Modules linked in:
   [160.634][ T1187] CPU: 0 UID: 0 PID: 1187 Comm: kworker/u8:10 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
   [160.634][ T1187] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
   [160.634][ T1187] Workqueue: btrfs-endio-write btrfs_work_helper
   [160.634][ T1187] RIP: 0010:btrfs_add_delayed_iput+0x2e3/0x340
   [160.634][ T1187] Code: 53 a3 45 (...)
   [160.634][ T1187] RSP: 0018:ffffc900065d77c8 EFLAGS: 00010293
   [160.634][ T1187] RAX: ffffffff83e5f502 RBX: ffff88805aba0000 RCX: ffff888029768000
   [160.634][ T1187] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
   [160.634][ T1187] RBP: dffffc0000000000 R08: 0000000000000000 R09: 0000000000000000
   [160.634][ T1187] R10: dffffc0000000000 R11: ffffed100b574497 R12: 0000000000000001
   [160.634][ T1187] R13: dffffc0000000000 R14: ffff888061194788 R15: 0000000000000200
   [160.634][ T1187] FS:  0000000000000000(0000) GS:ffff888126186000(0000) knlGS:0000000000000000
   [160.634][ T1187] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
   [160.634][ T1187] CR2: 00007fe553a3f000 CR3: 00000000596c2000 CR4: 00000000003526f0
   [160.634][ T1187] Call Trace:
   [160.634][ T1187]  <TASK>
   [160.634][ T1187]  btrfs_put_ordered_extent+0x18f/0x430
   [160.634][ T1187]  btrfs_finish_one_ordered+0xf63/0x2680
   [160.634][ T1187]  ? __pfx_btrfs_finish_one_ordered+0x10/0x10
   [160.634][ T1187]  ? do_raw_spin_lock+0x12b/0x2f0
   [160.634][ T1187]  ? lock_acquire+0x106/0x350
   [160.634][ T1187]  ? __pfx_do_raw_spin_lock+0x10/0x10
   [160.634][ T1187]  btrfs_work_helper+0x38b/0xc20
   [160.634][ T1187]  ? process_scheduled_works+0xa70/0x1860
   [160.634][ T1187]  process_scheduled_works+0xb5d/0x1860
   [160.634][ T1187]  ? __pfx_process_scheduled_works+0x10/0x10
   [160.634][ T1187]  ? assign_work+0x3d5/0x5e0
   [160.634][ T1187]  worker_thread+0xa53/0xfc0
   [160.634][ T1187]  kthread+0x388/0x470
   [160.634][ T1187]  ? __pfx_worker_thread+0x10/0x10
   [160.635][ T1187]  ? __pfx_kthread+0x10/0x10
   [160.635][ T1187]  ret_from_fork+0x514/0xb70
   [160.635][ T1187]  ? __pfx_ret_from_fork+0x10/0x10
   [160.635][ T1187]  ? __switch_to+0xc79/0x1410
   [160.635][ T1187]  ? __pfx_kthread+0x10/0x10
   [160.635][ T1187]  ret_from_fork_asm+0x1a/0x30
   [160.635][ T1187]  </TASK>
   [160.635][ T1187] Kernel panic - not syncing: kernel: panic_on_warn set ...

It means we add a delayed iput created after we last ran delayed iputs in
close_ctree() and set the flag BTRFS_FS_STATE_NO_DELAYED_IPUT in fs_info.

This happens when using autodefrag and more likely to happen if we use
flushoncommit too. The steps are the following:

1) Unmount starts, all delalloc is flushed and we enter close_ctree();

2) In close_ctree() we park the cleaner kthread, but while we wait for it
   to park, it's in:

     btrfs_run_defrag_inodes()
        btrfs_run_defrag_inode()
           btrfs_defrag_file()
              defrag_one_cluster()
                 defrag_one_range()
                    defrag_one_locked_target()

   And dirties some folios from an inode;

3) The cleaner kthread parks and we proceed in close_ctree(), waiting
   for all ordered extents, running delayed iputs and setting the flag
   BTRFS_FS_STATE_NO_DELAYED_IPUT in fs_info;

4) Later in close_ctree() we call btrfs_commit_super(), which commits the
   current transaction. Because we are mounted with flushoncommit, the
   transaction commit flushes delalloc and waits for the resulting ordered
   extent to complete;

5) The ordered extents from the flushed delalloc created by autodefrag
   complete and create delayed iputs, triggering the warning:

     WARN_ON_ONCE(test_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state));

   in btrfs_add_delayed_iput()

6) Further below in close_ctree() we will hit the following assertion:

     ASSERT(list_empty(&fs_info->delayed_iputs));

   Since we don't expect any more delayed iputs.

Fix this by flushing delalloc and waiting for the ordered extents right
after we parked the cleaner kthread and waiting for autodefrag in
close_ctree().

Reported-by: syzbot+6a843bf8604711c8fab0@syzkaller.appspotmail.com
Link: https://lore.kernel.org/linux-btrfs/6a1ee507.b4221f80.1326c5.0004.GAE@google.com/
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:17:12 +02:00
Filipe Manana
ba02eab280 btrfs: defrag: fix deadlock between defrag and delalloc space reservation
While running fsstress with autodefrag and flushoncommit, hit a deadlock
due to the fact that defrag reserves delalloc space while it's holding
dirty and locked folios, besides the extent range lock. The stack traces
are the following:

   [958.624] task:kworker/u50:3   state:D stack:0     pid:20365 tgid:20365 ppid:2      task_flags:0x4208060 flags:0x00080000
   [958.626] Workqueue: events_unbound btrfs_async_reclaim_metadata_space [btrfs]
   [958.627] Call Trace:
   [958.628]  <TASK>
   [958.628]  __schedule+0x4be/0x10f0
   [958.629]  ? preempt_count_add+0x69/0xa0
   [958.630]  schedule+0x26/0xd0
   [958.631]  wait_current_trans+0x102/0x160 [btrfs]
   [958.632]  ? __pfx_autoremove_wake_function+0x10/0x10
   [958.633]  start_transaction+0x374/0x900 [btrfs]
   [958.634]  btrfs_commit_current_transaction+0x1d/0x70 [btrfs]
   [958.635]  flush_space+0xca/0x5e0 [btrfs]
   [958.636]  ? _raw_spin_unlock+0x15/0x30
   [958.637]  ? btrfs_reduce_alloc_profile+0x8c/0x190 [btrfs]
   [958.639]  ? _raw_spin_unlock+0x15/0x30
   [958.640]  ? calc_available_free_space.isra.0+0x6f/0x110 [btrfs]
   [958.641]  do_async_reclaim_metadata_space+0x84/0x190 [btrfs]
   [958.642]  btrfs_async_reclaim_metadata_space+0x64/0x80 [btrfs]
   [958.644]  process_one_work+0x19d/0x3a0
   [958.644]  worker_thread+0x1c4/0x330
   [958.645]  ? __pfx_worker_thread+0x10/0x10
   [958.646]  kthread+0xfc/0x130
   [958.647]  ? __pfx_kthread+0x10/0x10
   [958.648]  ret_from_fork+0x1f7/0x2c0
   [958.648]  ? __pfx_kthread+0x10/0x10
   [958.649]  ret_from_fork_asm+0x1a/0x30
   [958.650]  </TASK>
   [958.651] task:kworker/u49:7   state:D stack:0     pid:52990 tgid:52990 ppid:2      task_flags:0x4208060 flags:0x00080000
   [958.653] Workqueue: writeback wb_workfn (flush-btrfs-334)
   [958.655] Call Trace:
   [958.655]  <TASK>
   [958.656]  __schedule+0x4be/0x10f0
   [958.657]  ? __blk_flush_plug+0xe9/0x140
   [958.658]  schedule+0x26/0xd0
   [958.658]  io_schedule+0x42/0x70
   [958.659]  folio_wait_bit_common+0x12b/0x330
   [958.660]  ? folio_wait_bit_common+0x100/0x330
   [958.662]  ? __pfx_wake_page_function+0x10/0x10
   [958.663]  extent_write_cache_pages+0x599/0x830 [btrfs]
   [958.664]  ? acpi_fwnode_get_reference_args+0x1fa/0x270
   [958.665]  btrfs_writepages+0x77/0x130 [btrfs]
   [958.666]  ? __pfx_end_bbio_data_write+0x10/0x10 [btrfs]
   [958.667]  do_writepages+0xc6/0x160
   [958.668]  __writeback_single_inode+0x42/0x310
   [958.669]  writeback_sb_inodes+0x231/0x570
   [958.670]  wb_writeback+0x8a/0x340
   [958.671]  wb_workfn+0xbf/0x450
   [958.672]  ? finish_task_switch.isra.0+0xc1/0x350
   [958.673]  process_one_work+0x19d/0x3a0
   [958.673]  worker_thread+0x1c4/0x330
   [958.674]  ? __pfx_worker_thread+0x10/0x10
   [958.675]  kthread+0xfc/0x130
   [958.676]  ? __pfx_kthread+0x10/0x10
   [958.676]  ret_from_fork+0x1f7/0x2c0
   [958.677]  ? __pfx_kthread+0x10/0x10
   [958.678]  ret_from_fork_asm+0x1a/0x30
   [958.679]  </TASK>
   [958.679] task:btrfs-cleaner   state:D stack:0     pid:296750 tgid:296750 ppid:2      task_flags:0x208040 flags:0x00080000
   [958.681] Call Trace:
   [958.682]  <TASK>
   [958.682]  __schedule+0x4be/0x10f0
   [958.683]  schedule+0x26/0xd0
   [958.684]  handle_reserve_ticket+0x1b9/0x2c0 [btrfs]
   [958.685]  ? __pfx_autoremove_wake_function+0x10/0x10
   [958.686]  reserve_bytes+0x283/0x4c0 [btrfs]
   [958.687]  btrfs_reserve_metadata_bytes+0x18/0xb0 [btrfs]
   [958.688]  btrfs_delalloc_reserve_metadata+0x121/0x320 [btrfs]
   [958.690]  btrfs_delalloc_reserve_space+0x46/0xb0 [btrfs]
   [958.691]  btrfs_defrag_file+0x903/0x1110 [btrfs]
   [958.692]  btrfs_run_defrag_inodes+0x334/0x430 [btrfs]
   [958.694]  cleaner_kthread+0x97/0x1c0 [btrfs]
   [958.694]  ? __pfx_cleaner_kthread+0x10/0x10 [btrfs]
   [958.696]  kthread+0xfc/0x130
   [958.696]  ? __pfx_kthread+0x10/0x10
   [958.697]  ret_from_fork+0x1f7/0x2c0
   [958.698]  ? __pfx_kthread+0x10/0x10
   [958.699]  ret_from_fork_asm+0x1a/0x30
   [958.700]  </TASK>
   [958.716] task:fsstress        state:D stack:0     pid:296769 tgid:296769 ppid:296768 task_flags:0x400140 flags:0x00080000
   [958.718] Call Trace:
   [958.719]  <TASK>
   [958.719]  __schedule+0x4be/0x10f0
   [958.720]  ? preempt_count_add+0x69/0xa0
   [958.721]  schedule+0x26/0xd0
   [958.722]  wb_wait_for_completion+0x79/0xc0
   [958.723]  ? __pfx_autoremove_wake_function+0x10/0x10
   [958.724]  __writeback_inodes_sb_nr+0xc5/0xf0
   [958.725]  try_to_writeback_inodes_sb+0x55/0x70
   [958.726]  btrfs_commit_transaction+0x19d/0xeb0 [btrfs]
   [958.727]  ? start_transaction+0x343/0x900 [btrfs]
   [958.728]  btrfs_mksubvol+0x28b/0x4e0 [btrfs]
   [958.729]  btrfs_mksnapshot+0x74/0xa0 [btrfs]
   [958.730]  __btrfs_ioctl_snap_create+0x194/0x210 [btrfs]
   [958.732]  btrfs_ioctl_snap_create_v2+0xef/0x150 [btrfs]
   [958.733]  btrfs_ioctl+0x7ec/0x2a70 [btrfs]
   [958.734]  ? __virt_addr_valid+0xe4/0x180
   [958.735]  ? __check_object_size+0x1cd/0x1f0
   [958.736]  ? kmem_cache_free+0x146/0x380
   [958.737]  ? _raw_spin_unlock+0x15/0x30
   [958.738]  ? do_sys_openat2+0x83/0xd0
   [958.739]  __x64_sys_ioctl+0x92/0xe0
   [958.740]  do_syscall_64+0x60/0x590
   [958.741]  ? clear_bhb_loop+0x60/0xb0
   [958.742]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
   [958.743] RIP: 0033:0x7f4431e108db
   [958.744] RSP: 002b:00007ffcd147db20 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
   [958.746] RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f4431e108db
   [958.747] RDX: 00007ffcd147eb90 RSI: 0000000050009417 RDI: 0000000000000005
   [958.749] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
   [958.751] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffcd147fbf0
   [958.752] R13: 00007ffcd147eb90 R14: 0000000000000005 R15: 0000000000000003
   [958.754]  </TASK>

What happens is the following:

1) The cleaner kthread is running autodefrag, and in defrag_one_range()
   it acquired all the folios for the range and locked them.

   Then it locked the extent range in the inode's iotree.

   It got two subranges from defrag_collect_targets(), the first one
   with folio A and the second one with folio B.

   After it defragged the first subrange, folio A remains locked and
   dirty - it's only unlocked when defrag_one_range() returns.

   When it attempts to defrag the second subrange (containing folio B),
   btrfs_delalloc_reserve_space() creates a space reservation ticket,
   due to lack of free metadata space and blocks waiting for the async
   metadata reclaim task to free space and wake it up;

2) The async reclaim metadata task attempts to commit the current
   transaction, but it blocks because there is another task that
   started the commit first;

3) A task creating a snapshot is committing the transaction and
   because the fs was mounted with flushoncommit, it calls
   try_to_writeback_inodes_sb(), which spawns a task to flush
   delalloc and waits for it to complete;

4) The task flushing delalloc (kworker/u49:7), finds that folio A for
   the inode being defragged is dirty, so it tries to lock it...

   But it blocks because folio A is locked by the defrag task (the
   cleaner kthread) which is blocked waiting for the reservation
   ticket to be served, but the async reclaim metadata task is
   blocked waiting for the transaction commit, which in turn is
   blocked waiting for the delalloc flush task, which is trying to
   lock folio A, resulting in a deadlock.

The same type of problem can happen if the async reclaim task starts to
flush delalloc, as that requires both locking the folio and the extent
range in the inode's io tree, and in this case we don't need the fs to
be mounted with flushoncommit. This type of problem has ocurred several
times in the past with reflinks for example, where we had a dirty folio
while holding the extent range locked and then starting a transaction
blocked waiting for the async reclaim task due to lack of free metadata
space.

So fix this by reserving delalloc space before locking folios and locking
the extent range in the inode's iotree. We can not simply unlock the
folios for each subrange given by defrag_collect_targets() after we defrag
it because the same folio may be present too in the next subrange (due to
large folios).

Fixes: 22b398eeee ("btrfs: defrag: introduce helper to defrag a contiguous prepared range")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
49a75e200d btrfs: remove btrfs_fs_info::stripesize
Btrfs does not support variable stripe length yet, all RAID0/5/6/10
chunks have the fixed stripe length 64K for now.

Furthermore, btrfs_fs_info::stripesize is not the real chunk stripe
length, it's always the same value as sectorsize.

Remove btrfs_fs_info::stripesize, and for the only callsite utilizing
that member, replace it with fs_info->sectorsize instead.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
f1df52e323 btrfs: use correct type for sectorsize/nodesize/blocksize
The nodesize and sectorsize are all u32 values, there is no need to use
u64 for local usage.

Furthermore some call sites also use "blocksize" or "bs" for sectorsize,
also change them to use the minimal type u32 instead.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Filipe Manana
bd3dddec1b btrfs: send: fix is_current_inode_path() to avoid path resets for common prefixes
In case the current inode's path is a prefix of the given path, the helper
is_current_inode_path() will return true, which causes the single caller
to reset the current inode's path. While this is not a functional issue,
it makes the caller recompute the current inode's path later. It could
also become a problem in the future in case get new callers for
is_current_inode_path() in more sensitive contexts.

Example: the current inode path is "/foo/bar" and the path we compare
against is "/foo/bar_xyz".

Fix this by returning true only if we have exact matches.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Filipe Manana
a4cea1272c btrfs: send: fix comment for SEND_MAX_DIR_UTIMES_CACHE_SIZE
The comment is wrong, because it's not about storing the ID of new
directories that were already created, instead it's about storing utimes
values for directories (both new and existing). The comment is wrong
because it was copy pasted from SEND_MAX_DIR_CREATED_CACHE_SIZE, but
forgot to update it afterwards.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Johannes Thumshirn
e549093c11 btrfs: zoned: don't force read-only on transient -EAGAIN from reloc merge
On a zoned FS, btrfs_delayed_refs_rsv_refill() returns -EAGAIN whenever
the over-committed metadata plus the zone_unusable bytes exceeds the
usable size in a metadata block-group to avoid heavy over-commit of
metadata and early ENOSPC in one transaction.

If this happens while doing reclaim, the transaction is getting aborted.

Treat -EAGAIN as a soft, retryable condition in case of block-group
reclaim.

Reported-by: Damien Le Moal <dlemoal@kernel.org>
Fixes: 7bcb04de98 ("btrfs: zoned: cap delayed refs metadata reservation to avoid overcommit")
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
097cdc8462 btrfs: allow any block size that is no larger than page size
Since v5.15 btrfs has support for block size < page size, but we still
only support 4K block size, while there is no special reason that we
cannot support 8K/16K/32K block sizes for 64K page size.

That 4K limit is completely arbitrary, and mostly to reduce test runtime
so we do not need to test all the extra block size combinations.

However that also limits the user choices, some users may understand
what they are doing, and want larger block sizes.  In that case, fixed
4K block size for subpage routine is blocking our way.

Just remove that fixed 4K requirement for block size < page size.

This should not affect regular end users, since mkfs is already using 4K
block size as default for quite a while, and the existing bs == ps support is
always there.

But for power users, this allows extra block size support, and may
provide extra test coverage.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
6eb2fe0724 btrfs: remove out-of-date comments regarding 2K block size
Since commit bac3c2910c ("btrfs: remove 2K block size support") there
is no 2K block size support inside btrfs anymore.

Remove the stale comments of btrfs_supported_blocksize().

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
545e560a5b btrfs: disable v1 space cache
V2 space cache has been the default mkfs option since btrfs-progs v5.15,
and commit 1e7bec1f7d ("btrfs: emit a warning about space cache v1
being deprecated") has already added a warning to show v1 space cache
has been deprecated.

It has been long enough that we should remove v1 space cache completely.

As the first step, disable v1 space cache by:

- Make "space_cache" mount option fallback to "nospace_cache"

- Make "space_cache=v1" fall back to "nospace_cache"

  This is safer than forcing "space_cache=v2", as forcing v2 cache
  requires removal of v1 cache and regenerating v2 cache.
  Such operation can be slow, and takes extra metadata space, thus
  it is not always safe for existing filesystems.

With this done, v1 cache mount will always fallback to nospace cache,
and mount option will not be able to force v1 space cache usage.

For example, even for a fs with v1 cache:

  # btrfs ins dump-super test.img
  superblock: bytenr=65536, device=test.img
  ---------------------------------------------------------
  csum_type		0 (crc32c)
  csum_size		4
  csum			0xdce44b2c [match]
  bytenr		65536
  flags			0x1
  			( WRITTEN )
  magic			_BHRfS_M [match]
  fsid			7d7c3bba-8211-4206-868d-10eedd5703f8
  metadata_uuid		00000000-0000-0000-0000-000000000000
  label
  generation		9
  root			30605312
  [...]
  compat_ro_flags	0x0                     <<< No FST feature
  incompat_flags	0x361
  			( MIXED_BACKREF |
  			  BIG_METADATA |
  			  EXTENDED_IREF |
  			  SKINNY_METADATA |
  			  NO_HOLES )
  cache_generation	9                       <<< Matches generation
  uuid_tree_generation	9

Attempting to mount it will lead to no space cache other than v1 space cache:

  # mount test.img /mnt/btrfs
  # dmesg -t | tail -n 5
  BTRFS: device fsid 7d7c3bba-8211-4206-868d-10eedd5703f8 devid 1 transid 9 /dev/loop0 (7:0) scanned by mount (1264)
  BTRFS info (device loop0): first mount of filesystem 7d7c3bba-8211-4206-868d-10eedd5703f8
  BTRFS info (device loop0): using crc32c checksum algorithm
  BTRFS info (device loop0): turning on async discard
  BTRFS info (device loop0): last unmount of filesystem 7d7c3bba-8211-4206-868d-10eedd5703f8

Even forcing v1 cache will not work, but fallback to the usual
nospace_cache:

  # mount test.img -o space_cache=v1 /mnt/btrfs
  # dmesg -t | tail -n 6
  BTRFS warning: v1 space cache is deprecated, fallback to no space cache
  BTRFS: device fsid 7d7c3bba-8211-4206-868d-10eedd5703f8 devid 1 transid 9 /dev/loop0 (7:0) scanned by mount (1264)
  BTRFS info (device loop0): first mount of filesystem 7d7c3bba-8211-4206-868d-10eedd5703f8
  BTRFS info (device loop0): using crc32c checksum algorithm
  BTRFS info (device loop0): turning on async discard
  BTRFS info (device loop0): last unmount of filesystem 7d7c3bba-8211-4206-868d-10eedd5703f8

And there will be no way to force converting a v2 cache back to v1, such
attempt will only clear free space tree and fallback to no space cache.

  # mkfs.btrfs -f -O fst,^bgt test.img
  # mount -o clear_cache,space_cache=v1 test.img /mnt/btrfs
  # dmesg -t | tail -n 11
  BTRFS warning: v1 space cache is deprecated, fallback to no space cache
  BTRFS: device fsid f59daad2-3ab5-4f33-b752-a36cfb09b674 devid 1 transid 8 /dev/loop0 (7:0) scanned by mount (1419)
  BTRFS info (device loop0): first mount of filesystem f59daad2-3ab5-4f33-b752-a36cfb09b674
  BTRFS info (device loop0): using crc32c checksum algorithm
  BTRFS info (device loop0): rebuilding free space tree
  BTRFS info (device loop0): disabling free space tree
  BTRFS info (device loop0): clearing compat-ro feature flag for FREE_SPACE_TREE (0x1)
  BTRFS info (device loop0): clearing compat-ro feature flag for FREE_SPACE_TREE_VALID (0x2)
  BTRFS info (device loop0): checking UUID tree
  BTRFS info (device loop0): turning on async discard
  BTRFS info (device loop0): force clearing of disk cache
  # mount | grep /mnt/btrfs
  /mnt/test.img on /mnt/btrfs type btrfs (rw,relatime,discard=async,nospace_cache,subvolid=5,subvol=/)

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Qu Wenruo
0d99b3b1cf btrfs: log swapfile activation/deactivation and warn about pinned block groups
A swap file on btrfs will pin down block groups that cover the swap file
extent.

Pinned down block groups will be skipped for scrub and relocation.

These degradation on critical btrfs maintenance operations is never
properly educated to end users, and have already caused problems
including:

- Scrub finished too quick
  Because the enabled swap file has pinned down most of the block
  groups. Thus any file extents in those block groups, even not utilized
  by the swap file, will be skipped from scrub.

- Unbalanced data and metadata usage, meanwhile relocation won't help
  The same reason, pinned down block groups will not be considered as
  relocation target, thus data extents that are not utilized by the swap
  file can still be skipped from relocation.

Although we already have kernel messages for both scrub and balance, the
balance one is still info level.

To better communicate those potential long term problems, add the
following output into dmesg:

- Change the message level to warn for __btrfs_balance()

- Total pinned down block group number and size during swapfile activation
- Total released block group number and size during swapfile deactivation
  The above messages have info level.

- The fact that pinned down block groups will not be scrubbed nor
  balanced
  The above message has warning level.

The example output would look like the following, for enabling a 1.2G
swapfile, which pinned down 2G block groups:

 BTRFS info (device dm-3): swapfile activated on root 5 ino 257, pinned down 2147483648 bytes from 2 block group(s)
 BTRFS warning (device dm-3): block groups with swapfile extents will not be scrubbed or balanced
 Adding 1257468k swap on /mnt/btrfs/foobar.  Priority:-1 extents:1 across:1257468k
 BTRFS info (device dm-3): swapfile deactivated on root 5 ino 257, released 2147483648 bytes from 2 block group(s)

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Boris Burkov
030d3514c6 btrfs: release extent lock per folio in readahead
In Meta production, we have observed a large number of hosts running
kernels newer than 6.13 which hit hung tasks on
btrfs_read_folio()->lock_extents_for_read(). Looking through the history
in this codepath reveals an interesting history.

in 6.12, we merged
commit ac325fc2aa ("btrfs: do not hold the extent lock for entire read")
which holds the extent lock very narrowly while looking up the
extent_map. However, this proved to introduce a serious race with DIO
writes which was fixed in 6.14 with
commit acc18e1c1d ("btrfs: fix stale page cache after race between readahead and direct IO write")

That latter fix subtly changed the extent unlock point from the pre-6.12
regime. In 6.11, each read endio unlocked the extent it finished
reading, but in 6.14, the extent is locked/unlocked as a unit around the
entire readahead loop, while the individual folios are still unlocked as
the endios finish. This is mostly the same behavior, as all successful
reads will populate the page cache, so subsequent reads won't enter
btrfs and hit the extent lock. But in the case where the readahead
fails, perhaps because of a memory allocation failure doing compressed
reads, the page will not be brought up to date and a later read of an
overlapping range *will* block on the extent lock.

Why is this a problem?

On sufficiently large loaded systems, I have observed that direct
reclaim can run for minutes. Given that, consider two tasks on such a
system reading an overlapping range of a compressed file:

  Task 1 locks the whole range and starts to read. Some allocation for
  the compressed read for folio F fails and we carry on while holding the
  extent lock for the full range.

  Task 2 wants to read F, which is not uptodate and in page cache, so it
  blocks on the extent lock held by Task 1.

  Task 1 keeps getting stuck in direct reclaim (likely, we already
  supposed an allocation failure above)

  Task 2 stays blocked on the extent lock the whole time.

If you consider the effects of readahead_expand and imagine a file with
a 128k compressed extent followed by many smaller compressed extents,
you can imagine that the expanded window will result in subsequent reads
hitting many extents (128k/4k = 32) per lock window in the worst case.

The system likeley wouldn't be all that healthy anyway, so this is
likely not a critical improvement, but it does alleviate this one source
of stress and one thread's slowdown escalating to others.

To bring this behavior back to the old model, we should unlock the
extent at each loop of the readahead loop rather than in one shot at the
end. This allows such overlapping reads to proceed as they should.
Writes are fine because either the page has already been read and has an
appropriate state in the page cache to be invalidated (or not uptodate)
or it is still-to-be-read and the extent lock is still held protecting
it.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:28 +02:00
Filipe Manana
0a9c35d304 btrfs: fix copy_remapped_data() to not allocate more memory than intended
The loop intends to copy the data in chunks up to 1M but we allocate the
pages array for the entire length and don't cap it to 1M. Fix this by
computing 'nr_pages' using 'copy_len' instead of 'length'.

While at it, also make 'nr_pages' and 'copy_len' const, as they never
change, to make the code more clear.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Filipe Manana
6f1c97695a btrfs: fix memory barrier order in reloc_root_is_dead()
When we set a root's reloc_root to NULL, we do it like this:

   static void clear_reloc_root(struct btrfs_root *root)
   {
       root->reloc_root = NULL;
       /*
        * Need barrier to ensure clear_bit() only happens after
        * root->reloc_root = NULL. Pairs with have_reloc_root().
        */
        smp_wmb();
        clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
   }

So that a NULL reloc_root is always seen before seeing that the bit
BTRFS_ROOT_DEAD_RELOC_TREE was cleared.

But on the read side we have:

   static bool reloc_root_is_dead(const struct btrfs_root *root)
   {
        smp_rmb();
        if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
            return true;
        return false;
   }

And then callers of reloc_root_is_dead() access root->reloc_root.

Because the read memory barrier is placed before testing the bit, the CPU
is completely free to speculatively reorder those two loads. It can read
root->reloc_root before it actually checks the dead tree bit.

Sashiko reported this as an existing problem in another patch review, see
the link in the Link tag below.

Fix this by moving the read memory barrier to happen after testing the bit
and update the comment to reflect current reality.

Link: https://sashiko.dev/#/patchset/cf84f1a217c719e25b6b69e4298dd7afd36c9427.1781194426.git.fdmanana%40suse.com
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Qu Wenruo
15f7c86215 btrfs: do not overwrite NODATASUM flag when removing NODATACOW flag
[TEST FAILURE]
The test case generic/628 will fail if MOUNT_OPTIONS is set to
"-o nodatasum":

  FSTYP         -- btrfs
  PLATFORM      -- Linux/x86_64 btrfs-vm 7.1.0-rc4-custom+ #383 SMP PREEMPT_DYNAMIC Sat May 30 07:35:42 ACST 2026
  MKFS_OPTIONS  -- -O bgt -K /dev/mapper/test-scratch1
  MOUNT_OPTIONS -- -o nodatasum /dev/mapper/test-scratch1 /mnt/scratch

  generic/628  1s ... - output mismatch (see /home/adam/xfstests/results//generic/628.out.bad)
     --- tests/generic/628.out	2022-05-11 11:25:30.816666664 +0930
     +++ /home/adam/xfstests/results//generic/628.out.bad	2026-06-08 18:56:49.878542927 +0930
     @@ -8,8 +8,9 @@
      310f146ce52077fcd3308dcbe7632bb2  SCRATCH_MNT/a
      310f146ce52077fcd3308dcbe7632bb2  SCRATCH_MNT/d
      test reflink flag not set iflag
     +XFS_IOC_CLONE: Invalid argument
      310f146ce52077fcd3308dcbe7632bb2  SCRATCH_MNT/a
     -310f146ce52077fcd3308dcbe7632bb2  SCRATCH_MNT/b
     +d41d8cd98f00b204e9800998ecf8427e  SCRATCH_MNT/b
     ...

[CAUSE]
The direct cause is that after "chattr +S", the btrfs inode will lose its
NODATASUM flag inherited from the mount option. E.g.:

  # mkfs.btrfs -f $dev
  # mount $dev $mnt -o nodatasum
  # touch $mnt/foobar
  # sync
  # btrfs ins dump-tree -t 5 $dev | grep "(257 INODE_ITEM 0) itemoff" -A 3
         item 4 key (257 INODE_ITEM 0) itemoff 15879 itemsize 160
         	generation 9 transid 9 size 0 nbytes 0
         	block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
         	sequence 1 flags 0x1(NODATASUM)
         	                     ^^^^^^^^^ Proper NODATASUM flag

  # chattr +S $mnt/foobar
  # sync
  # btrfs ins dump-tree -t 5 $dev | grep "(257 INODE_ITEM 0) itemoff" -A 3
  	item 4 key (257 INODE_ITEM 0) itemoff 15879 itemsize 160
         	generation 9 transid 10 size 0 nbytes 0
         	block group 0 mode 100644 links 1 uid 0 gid 0 rdev 0
         	sequence 2 flags 0x20(SYNC)
         	                      ^^^^ Only the new SYNC flag

This makes the inode drop the old NODATASUM flag, while the new reflink
destination will still inherit the NODATASUM flag.  The mismatching
NODATASUM flags will cause the reflink to fail.

The root cause is that, inside btrfs_fileattr_set() if no FS_NOCOW_FL is
set, we remove both NODATASUM and NODATACOW flag.

However we should not touch NODATASUM flag, as data COW doesn't require
checksum.  Only NODATACOW implies NODATASUM, but DATACOW doesn't imply
DATASUM.

The deeper problems are:

- Fileattr API is too binary
  It either clears or sets a flag, there is no "do not change" option.
  So that why "chattr +S" implies "chattr -C", and is forcing us to
  change NODATACOW along with NODATASUM flag.

- No way to change NODATASUM through fileattr API
  In fact NODATASUM can only be modified through mount option.

The deeper problems are much harder to attack.

[FIX]
Remove NODATACOW flag when FS_NOCOW_FL is not set, but only remove
NODATASUM if "nodatasum" mount option is not set.

This allows the existing "chattr +C" then "chattr -C" to remove
both NODATACOW and NODATASUM flags on a default mount.

But for a mount with "nodatasum" option, the NODATASUM inode flag will
persist through either "chattr +C" and "chattr -C".

Fixes: 7e97b8daf6 ("btrfs: allow setting NOCOW for a zero sized file via ioctl")
Cc: stable@vger.kernel.org
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Filipe Manana
872df0c80f btrfs: don't over reserve metadata space for property in btrfs_fileattr_set()
We are using 2 units for properties but we only set one property.
Fix this by using the correct amount: 1 unit.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Dongjiang Zhu
63a01c7578 btrfs: start qgroup ioctl transactions on the quota root
The qgroup ioctls update the quota tree, but they currently start their
transactions using the root of the inode passed to the ioctl. This makes
the transaction reservation depend on the path used for the ioctl instead
of the tree being modified.

Start qgroup ioctl transactions on the quota root instead. Take a reference
to fs_info->quota_root under qgroup_ioctl_lock before starting the
transaction, because quota disable can clear and put fs_info->quota_root
after the early quota-enabled check. Keep the reference until the
transaction handle is ended.

Suggested-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Dongjiang Zhu <zhudongjiang@fnnas.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Qu Wenruo
4ac48dc0cb btrfs: refactor btrfs_dio_iomap_end()
That function has the following problems:

- Read/write handling scattered across different locations
  E.g. At the beginning there is a dedicated hole read handling, but
  later short read handling is at an if() branch.

- Modifying of @pos and @length parameter for short read
  Although it's completely fine to modify those parameters as they are
  passed by value, but it can still be confusing to read.  As normally
  we would assume @pos and @length to be the original range.

  But for short IO handling we modify @pos/@length, and completely
  ignore @written.

- Unnecessary split for ordered extent and changeset handling
  Both OE and changeset are only for writes, but they are handled in two
  different if (write) {} blocks.

Refactor the function so that:

- Handling of reads and writes are concentrated in their code block
  Now the handling of reads are in its own small if () branch.

  Leaving the more complex writes handling to take the remaining
  function, and reduce the indent level.

  This also removes all unnecessary "if (write)" checks.

- Do not modify @pos and @length
  Let short IO handling to manually calculate the remaining range.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Qu Wenruo
9366afd430 btrfs: remove btrfs_dio_data::submitted
This member records how many bytes are submitted for a direct
read/write, utilized by iomap_end() callback to handle short IO cases.

However iomap_end() callback is already providing an internally tracked
@written member, which is doing the same accounting and providing the
same value as btrfs_dio_data::submitted.

There is no need to duplicate the work, just remove btrfs_dio_data::submitted.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2026-08-07 19:16:27 +02:00
Linus Torvalds
a13307e97d BPF fixes:
- Fix BPF verifier to preserve full pointer state for commuted
   scalar += pointer arithmetic (Yiyang Chen, Eduard Zingerman)
 
 - Fix a use-after-free of request sockets in the BPF TCP
   iterator batching (Jose Fernandez)
 
 - Fix a use-after-free of sk_redir in the BPF sockmap send
   verdict path (Chengfeng Ye)
 
 - Fix a netns reference imbalance in the BPF conntrack kfuncs
   (Chengfeng Ye)
 
 - Fix bpf_get_fsverity_digest() dynptr assumptions and silent
   digest truncation (Eric Biggers)
 
 - Fix bpf_tcp_{gen,check}_syncookie to check sk_state before
   sk_protocol to make sure it is a full socket (Luxiao Xu)
 
 - Fix rqspinlock to reset the tail when preserving the queue
   on deadlock (Kumar Kartikeya Dwivedi)
 
 Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
 -----BEGIN PGP SIGNATURE-----
 
 iIsEABYKADMWIQTFp0I1jqZrAX+hPRXbK58LschIgwUCanXeCRUcZGFuaWVsQGlv
 Z2VhcmJveC5uZXQACgkQ2yufC7HISIMfLQD9EWzi5MVBTcvg0XsHY1GZZBZUpfwo
 VCrfPm9vHAVuqQ0A/0D9vWVRf1UEk9ccn+ebVKPuTuydGnDRR0Qovuca4gQF
 =jZY8
 -----END PGP SIGNATURE-----

Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Pull BPF fixes from Daniel Borkmann:

 - Fix BPF verifier to preserve full pointer state for commuted
   scalar += pointer arithmetic (Yiyang Chen, Eduard Zingerman)

 - Fix a use-after-free of request sockets in the BPF TCP iterator
   batching (Jose Fernandez)

 - Fix a use-after-free of sk_redir in the BPF sockmap send verdict
   path (Chengfeng Ye)

 - Fix a netns reference imbalance in the BPF conntrack kfuncs
   (Chengfeng Ye)

 - Fix bpf_get_fsverity_digest() dynptr assumptions and silent
   digest truncation (Eric Biggers)

 - Fix bpf_tcp_{gen,check}_syncookie to check sk_state before
   sk_protocol to make sure it is a full socket (Luxiao Xu)

 - Fix rqspinlock to reset the tail when preserving the queue
   on deadlock (Kumar Kartikeya Dwivedi)

* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  rqspinlock: Reset tail when preserving queue on deadlock
  bpf: Check sk_state before sk_protocol in bpf_tcp_*_syncookie
  fsverity: Fix silent truncation in bpf_get_fsverity_digest()
  fsverity: Fix bpf_get_fsverity_digest() dynptr assumptions
  bpf: tcp: Fix use-after-free in bpf_iter_tcp_established_batch()
  bpf: Fix netns reference imbalance in conntrack kfuncs
  bpf, sockmap: Fix sk_redir use-after-free in send verdict
  selftests/bpf: Cover commuted pointer state propagation
  bpf: Propagate untrusted pointer state in commuted arithmetic
  bpf: Preserve pointer state for commuted arithmetic
  bpf: Simplify sanitize_err() signature
2026-08-07 08:08:57 -07:00
Linus Torvalds
0150da6be1 s390:
- fix a lot of small bugs and races
 
 x86:
 - fix missing locking related to KVM_CAP_MOVE_ENC_CONTEXT_FROM
 
 - warn on creating a new page table that is the child of an invalid one,
   and limit damage before it's too late
 
 - disable use of INVLPGA when NPT is enabled, because it doesn't seem
   to flush TLBs correctly
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmp14g0UHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroPzrAf+KGSkR+qBbqgsSy0I86kw6VvX6h8i
 TySes/l0JaNbVQDDt3vYzw/ZXhrm6dRA58i1mwjIVLIY3pflXzUrwqqXjLwvcGNf
 1eX0jOZOg68fXPW22okR+7mNJdHSiRiX3Ozw20TrS5+33xN3dKa1xsTtNFRN99f6
 h8mtQIP5L9dYn6y9lI27y51lkx3Ojd8SWAUJyXn8d3OA28mBcIShpq6BJsroHT34
 HzibCnNAodFMGDsUJr93mpJisUV4EsWPKO2hzMm5FUUkV/JBD3GnqwF550Kwpc8a
 ojuaHCEAnZXLoDuOTBiT8iQBa1fDUHizERlTkHD91s0ktwqf+e3p0azjMw==
 =734T
 -----END PGP SIGNATURE-----

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull vkm fixes from Paolo Bonzini:
 "s390:

   - fix a lot of small bugs and races

  x86:

   - fix missing locking related to KVM_CAP_MOVE_ENC_CONTEXT_FROM

   - warn on creating a new page table that is the child of an invalid
     one, and limit damage before it's too late

   - disable use of INVLPGA when NPT is enabled, because it doesn't seem
     to flush TLBs correctly"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (26 commits)
  KVM: x86/mmu: WARN and clear role.invalid when creating a child shadow page
  KVM: SVM: Serialize accesses to the owner and mirror list with separate lock
  KVM: SVM: make svm_flush_tlb_gva do a full asid flush if NPT enabled
  KVM: s390: Fix cleanup in kvm_s390_pv_create_cpu()
  KVM: s390: Fix ordering when adding to SCA
  KVM: s390: Return -EINTR if a signal is pending while faulting-in
  KVM: s390: Free the mmu cache when kvm_arch_vcpu_create() fails
  KVM: s390: ucontrol: Add missing locking around gmap_remove_child()
  KVM: s390: cmma: Fix dirty tracking when removing memslot
  KVM: s390: Fix race in __do_essa()
  KVM: s390: Fix leaking of PGM_ADDRESSING to userspace
  KVM: s390: ucontrol: Fix sca_clear_ext_call()
  KVM: s390: Fix overclearing ESCA in case of error
  KVM: s390: Fix kvm_s390_vcpu_unsetup_cmma()
  KVM: s390: Do not free SCA if it was not allocated
  KVM: s390: Fix unlikely NULL gmap dereference
  s390/vfio_ccw: Implement a crw lock
  s390/vfio_ccw: Selectively expand io_mutex
  s390/vfio_ccw: Move cp cleanup out of not operational
  s390/vfio_ccw: Cancel existing workqueues
  ...
2026-08-07 07:41:40 -07:00
Linus Torvalds
7cbe91a4be Thermal control fixes for 7.2-rc7
Revert three thermal core updates, two recent ones and one older.
 
 The recent ones attempted to fix a design issue in the thermal core and
 simplify code on top of that, but they made changes visible to user
 space and made it unhappy.
 
 The older one is a misguided code cleanup that introduced a (potentially
 nasty) bug.
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmp1yVQSHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1gm8H/j6zXC1hbZbmLjQd9HSiNUgpuDOPMz9p
 5oeacpOiu60PUA8a0IEEdQGHlihg4eStP8h9cSoYccKCl9MtIFHZQluPKF1Dh6NM
 18749AZ0Ed2ZRZbar6ud+b88suUh9bTTWazjcwYoqr7vLtPO/1jFGDx4gED2LlEg
 c8CNeYzqO4KoG86qSe6gRtus6IigH0I95eFY/hlfzJrhU3v7GlGrWGuHKaNOZ85e
 Sv34E2UApV3s0VpU/zHpiFXJIP9eVYER8cHtUayZYOXc6wDf2jFfwYJixxn/T15F
 gUKpPUy0cOirobx1ZlQn5l5lVgtBuUj201XENcR1dfMINhdvuL6S1ik=
 =/1Jt
 -----END PGP SIGNATURE-----

Merge tag 'thermal-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control fixes from Rafael Wysocki:
 "Revert three thermal core updates, two recent ones and one older.

  The recent ones attempted to fix a design issue in the thermal core
  and simplify code on top of that, but they made changes visible to
  user space and made it unhappy.

  The older one is a misguided code cleanup that introduced a
  (potentially nasty) bug"

* tag 'thermal-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Revert "thermal/drivers/hwmon: Cleanup coding style a bit"
  Revert "thermal: hwmon: Register a hwmon device for each thermal zone"
  Revert "thermal: hwmon: Use extra_groups for adding temperature attributes"
2026-08-07 06:48:51 -07:00
Linus Torvalds
7e73882ecf sound fixes for 7.2-rc7
A collection of small fixes since the last pull request.
 More than few, but an enough-manageable amount at this time.
 
 USB-audio:
 - UAF, OOB and such hardening fixes for USB-audio, usx2y and us144mkii
 - Mixer regression fixes for Logitech PRO X 2 LIGHTSPEED headset and
   M-Audio Fast Track Ultra
 
 HD-audio:
 - Fix for an ACPI reference leak in TAS2781 HDA side-codec
 
 ASoC:
 - Fixes the default tables for Cirrus Logic codecs
 - Fixes for invalid enum accesses for Qualcomm LPASS
 - Error handling and robustness fixes for Intel SOF & Soundwire
 - DMI quirks for a few AMD devices
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAmp1mRAOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE+8iw/8DBwUZT7mnytHB+QHF/STnt/kIZN1Y8LSRXMy
 JegVVYVksW1b9nF/JAD02vl0CMJ/ZE3qQs1deMbbbF982tfATu1B0XzLO2AYXE5F
 50KLlmkyHfybHVKlYvwGRrKEUbYsBOcoeCaFPFS3gDQfkXepBMK4yE9db+qpZvcS
 ZLyv9Ff3rcsCfSTNyxCJdrfiespDC6H1Trj0CeGoyiHyNr5tKhQ6JByLjTLNjweF
 Mi2UNa+cy5zQV4kWiv+RvQ6CWAJyETF7oZQvHKYfybkqr4GiyDjSVl5usEGOUNdh
 vKuEIbzAprEmzQ/pjX27+ig53uiwDAMDGrRDwW3khqrm7XIDXEbL5iQNbBz5HRU5
 GjWCbbJGoqDCdDg9dN3nEACH2sX6kDYt8I5RKQo4l/+3tMISNrFujdCXrYQbx6We
 MLouuzjLbr+gyr2EVsKaNuZqVS6Li9OEwRloP7TJjI81UAaxfosMv+tmmB8d7P2v
 xjuBDObs2JgROPWy0lVI62/1cL/KLLMHM8z/+VlYxMtYJ13ipySeXCRtaHSMX46c
 76Vtgx42O3YOHTkNBg5zpRFTX7NnK0B7u8JWsYqb5HlLnvr1TeUWevq3UKAc/5mX
 suj747xYrYcI6nXFN9CTnfz/V3RjQqWKooBgjbKdTe2QHkynQd2GI6Kb6dYIJ/R8
 MFzD4EM=
 =r8TD
 -----END PGP SIGNATURE-----

Merge tag 'sound-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes since the last pull request. More than
  few, but an enough-manageable amount at this time.

  USB-audio:
   - UAF, OOB and such hardening fixes for USB-audio, usx2y and
     us144mkii
   - Mixer regression fixes for Logitech PRO X 2 LIGHTSPEED headset and
     M-Audio Fast Track Ultra

  HD-audio:
   - Fix for an ACPI reference leak in TAS2781 HDA side-codec

  ASoC:
   - Fixes the default tables for Cirrus Logic codecs
   - Fixes for invalid enum accesses for Qualcomm LPASS
   - Error handling and robustness fixes for Intel SOF & Soundwire
   - DMI quirks for a few AMD devices"

* tag 'sound-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (22 commits)
  ALSA: usb-audio: Fix sticky mixer regressions on M-Audio Fast Track Ultra
  ASoC: cs4265: sort the register default table
  ASoC: cs35l45: sort the register default table
  ASoC: cs35l41: sort the register default table
  ASoC: amd: yc: Add DMI quirk for MSI Raider A18 HX A7VHG
  ASoC: amd: yc: Add DMI quirk for Xiaomi RedmiBook 16 2025
  ALSA: usx2y: bound the hwdep mmap fault offset
  ALSA: usb-audio: fix OOB write on Type II inbound URBs
  ALSA: us144mkii: re-anchor capture URBs on resubmission
  ALSA: FCP: fix OOB write in fcp_meter_ctl_get()
  MAINTAINERS: add SpacemiT K1/K3 I2S entry
  ASoC: rt5645: Make the Kconfig symbol user selectable
  ALSA: usb-audio: Add QUIRK_FLAG_MIXER_GET_CUR_BROKEN for Logitech PRO X 2 LIGHTSPEED
  ALSA: hda/tas2781: fix ACPI reference handling
  ASoC: codecs: lpass-wsa-macro: Fix enum kcontrol accesses
  ASoC: codecs: lpass-tx-macro: Fix enum kcontrol accesses
  ASoC: SOF: ipc4-pcm: Continue the pipeline trigger in case of IPC timeout
  ASoC: amd: yc: Add DMI quirk for HP Victus Laptop 16-e1xxx
  ASoC/soundwire: Intel: reset the PCMSyCM registers in hda_sdw_bpt_close
  ASoC: SOF: sof-audio: Fix error path in sof_widget_setup_unlocked()
  ...
2026-08-07 06:36:11 -07:00
Takashi Iwai
a8934c2c6d ALSA: usb-audio: Fix sticky mixer regressions on M-Audio Fast Track Ultra
The recent fix for sticky mixer volumes caused regressions of M-audio
Fast Track Ultra device, where the mixer state is kept to the default
value.

Add the quirk entries to tolerate the broken mixer behavior.  As the
device is known to work in the implicit feedback mode, explicitly
enable the implicit feedback mode, too.

Since there are two FTU models that are almost identical, both entries
are added in this patch (0763:2080 and 0763:2081).

Fixes: 86aa1ea1f1 ("ALSA: usb-audio: Do not expose sticky mixers")
Link: https://bugzilla.suse.com/show_bug.cgi?id=1273166
Link: https://patch.msgid.link/20260807083418.1712585-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-08-07 10:35:31 +02:00
Sean Christopherson
5ec42d5765 KVM: x86/mmu: WARN and clear role.invalid when creating a child shadow page
Explicitly clear role.invalid when deriving a child shadow page's role from
its parent to harden against bugs elsewhere in KVM, as violating KVM's
invariant that invalid pages are NOT on the list of active MMU pages leads
to use-after-free due to __kvm_mmu_prepare_zap_page() using list_add()
instead of list_move() when processing an invalid shadow page, i.e. makes a
bad situation far worse.

Yell loudly if the parent is invalid, as it means KVM has missed a validity
check, i.e. KVM is attempting to map memory using an invalid/obsolete root,
but continue on as the child is otherwise still a valid shadow page.

  ==================================================================
  BUG: KASAN: slab-use-after-free in __kvm_mmu_get_shadow_page+0x1817/0x1860 [kvm]
  Write of size 8 at addr ff11000153dd1368 by task repro/853

  CPU: 1 UID: 1000 PID: 853 Comm: repro Not tainted 7.2.0-rc2-3aec122bdcaf-next-vm #5 PREEMPT
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  Call Trace:
   <TASK>
   dump_stack_lvl+0x4b/0x70
   print_report+0x153/0x49c
   kasan_report+0xbc/0xf0
   __kvm_mmu_get_shadow_page+0x1817/0x1860 [kvm]
   mmu_alloc_root+0x141/0x320 [kvm]
   kvm_mmu_load+0x612/0x20f0 [kvm]
   kvm_arch_vcpu_ioctl_run+0x3dd5/0x6150 [kvm]
   kvm_vcpu_ioctl+0x5e4/0x10d0 [kvm]
   __x64_sys_ioctl+0x131/0x1b0
   do_syscall_64+0x67/0x5f0
   entry_SYSCALL_64_after_hwframe+0x4b/0x53
   </TASK>

  Allocated by task 853:
   kasan_save_stack+0x20/0x40
   kasan_save_track+0x14/0x30
   __kasan_slab_alloc+0x5f/0x70
   kmem_cache_alloc_noprof+0xfe/0x2e0
   __kvm_mmu_topup_memory_cache+0x135/0x530 [kvm]
   paging64_page_fault+0x318/0x1e30 [kvm]
   kvm_mmu_do_page_fault+0x21d/0x630 [kvm]
   kvm_mmu_page_fault+0x18c/0x17b0 [kvm]
   kvm_arch_vcpu_ioctl_run+0x1f35/0x6150 [kvm]
   kvm_vcpu_ioctl+0x5e4/0x10d0 [kvm]
   __x64_sys_ioctl+0x131/0x1b0
   do_syscall_64+0x67/0x5f0
   entry_SYSCALL_64_after_hwframe+0x4b/0x53

  Freed by task 853:
   kasan_save_stack+0x20/0x40
   kasan_save_track+0x14/0x30
   kasan_save_free_info+0x3b/0x60
   __kasan_slab_free+0x43/0x70
   kmem_cache_free+0xe2/0x400
   kvm_mmu_commit_zap_page.part.0+0x1e2/0x310 [kvm]
   kvm_mmu_free_roots+0x283/0x560 [kvm]
   kvm_arch_vcpu_ioctl_run+0x33c8/0x6150 [kvm]
   kvm_vcpu_ioctl+0x5e4/0x10d0 [kvm]
   __x64_sys_ioctl+0x131/0x1b0
   do_syscall_64+0x67/0x5f0
   entry_SYSCALL_64_after_hwframe+0x4b/0x53

Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Fixes: a770f6f28b ("KVM: MMU: Inherit a shadow page's guest level count from vcpu setup")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2026-08-07 09:26:45 +02:00
Linus Torvalds
f9a2394a23 17 hotfixes. 15 are cc:stable. 16 are for MM.
There's a 3 patch series from Lorenzo "mm: fix UAF caused by race between
 ptdump and vmap pgtable freeing" which addresses a quite old bug in the
 ptdump code.
 
 And a 2 patch series also from Lorenzo which fixes a four year old bug in
 the huge_zero_folio handling.
 
 A 3 patch series from SJ fixes a few possible divide-by-zero issues which
 Sashiko sniffed out.  And a 2 patch series which fixes handling of the
 commit_inputs parameters.
 
 The remainder are singletons, please see their changelogs for details.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCanU4oAAKCRDdBJ7gKXxA
 jjNlAQC8cHxL4VjKRgSs90n6XQoYdLeIHxxRPVqfbfpRuQT/MQEAlg6+pCzlwMHW
 OZojHm4c7ttzU8X/VRkq6u8a95qSyAg=
 =P6ey
 -----END PGP SIGNATURE-----

Merge tag 'mm-hotfixes-stable-2026-08-06-18-44' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull MM fixes from Andrew Morton:
 "17 hotfixes.  15 are cc:stable.  16 are for MM.

  There's a patch series from Lorenzo "mm: fix UAF caused by race
  between ptdump and vmap pgtable freeing" which addresses a quite old
  bug in the ptdump code.

  And another series also from Lorenzo which fixes a four year old bug
  in the huge_zero_folio handling.

  A series from SJ fixes a few possible divide-by-zero issues which
  Sashiko sniffed out. And a series which fixes handling of the
  commit_inputs parameters.

  The remainder are singletons, please see their changelogs for details"

* tag 'mm-hotfixes-stable-2026-08-06-18-44' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  mm/damon: adjust isolated pages stat for DAMOS_MIGRATE_{HOT,COLD}
  mm/damon/ops-common: putback folios on invalid migrate nid
  mm/huge_memory: initialise workingset state before folio split
  mm/page_table_check: skip special zero mappings
  mm/damon/lru_sort: skip damon_call() if ctx has not started
  mm/damon/reclaim: skip damon_call() if ctx has not started
  mm/damon/lru_sort: error out for >10000 active_mem_bp
  samples/damon/mtier: error out for zero quota goal target values
  mailmap: map old addresses to Danila Tikhonov
  mm/huge_memory: separate out CONFIG_PERSISTENT_HUGE_ZERO_FOLIO logic
  mm/huge_memory: fix huge_zero_pfn race
  MAINTAINERS: update address for Brendan Jackman
  mm/filemap: __filemap_add_folio() restore index before retrying
  microblaze: restore the page alignment of swapper_pg_dir
  arm64: remove redundant concurrent ptdump UAF mitigation
  mm/ptdump: always stabilise against page table freeing using init_mm
  mm/vmalloc: acquire init_mm lock on huge vmap to avoid ptdump UAF
2026-08-06 20:29:38 -07:00
Linus Torvalds
364465ab19 three ksmbd server fixes
-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmp1LGcACgkQiiy9cAdy
 T1FDlQv9GlIzgib/35NXV/L50xHR5UeloUvH+U6xbWk+OOdYh58VpZory6MxcaP1
 uF87qqvs4JKFaBmOmYCodhChjF4lomn1ZcWSIrhx8k6nV+miIJrfofpTT3rI3DV8
 BYwfRPlxcUd7s79W6uCCEun70OQOrrZT8J3FSKa3Pr+ySDBVd4Q9TZLh6eW25EOf
 i4CUZv2LB2HGxtKXSS+B+vaP1k475b1W1InRW0Ir3Oj2amwnMst+g2wZx9rOVhMI
 gFfcgj3HDVlVO6QEYGEyrzPM1fMKBlpnUOVbKkLGRYJodCUTYSKFsZXd2ByJXZFx
 V9O5ZcyRgIfq4bOA7vBqrLi9eWJFOLavb7GUwDl9u7o51FHZT8Setk1kVkPypKJ2
 dQBQ4EVX3bMqjv+BRNv8GV1Q3qwPdbBbgRtanTg33POGmIDpRKcEPdcj3C3CIaBa
 QVfjDpmOJk/fvsQDEJfVF1rEE/qaqQ7/1+nai9Ze29nkAzNtNPUsgriv1x11Ax9m
 xHfq88yg
 =cLad
 -----END PGP SIGNATURE-----

Merge tag 'v7.2-rc6-smb3-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

 - Reject Pattern_V1 payloads when Pattern_V1 support was not
   negotiated

 - Validate compression transform flags and chained mode before
   allocating the decompression buffer

 - Enforce the pre-authentication PDU size limit before allocating
   the decompression buffer, preventing compressed requests from
   bypassing the limit

* tag 'v7.2-rc6-smb3-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: apply the pre-authentication PDU limit when decompressing
  ksmbd: validate compression Flags before kvmalloc
  smb: compress: reject Pattern_V1 when not negotiated
2026-08-06 20:25:46 -07:00
Kumar Kartikeya Dwivedi
7a3c0289c3 rqspinlock: Reset tail when preserving queue on deadlock
Currently, the destruction of the waiter queue is suppressed for
rqspinlock in cases where a deadlock is detected. Deadlock checks happen
relatively frequently (on entry for AA, within 1ms for ABBA), and waiter
threads may not be involved in locking scenarios involving deadlocks.
Thus, it is useful to not flush the queue and let other waiters take a
stab at acquiring the lock after we detect a deadlock and exit.

However, we need to follow the same logic as what we did previously for
the waitq_timeout label: reset the tail, and if we cannot, signal the
next waiter appropriately. In case of deadlocks, this signal would just
mark the MCS node as unlocked, and in case of timeouts, it would signal
RES_TIMEOUT_VAL. The difference thus is in the value propagated, which
decides whether the queue remains active or gets flushed.

Not doing the tail reset, and waiting for the next waiter can lead to
cases where we are the final waiter, and thus no next waiter arrives,
leading to intermittent stalls in this path. Once the next waiter does
join, we will be unblocked. In the theoretical case when the next waiter
never joins, we risk stalling indefinitely.

This can only happen for ABBA deadlocks, since entry into the wait queue
is guarded with AA checks. A precise sequence of executions leading up
to this scenario can be:

CPU 0 holds lock A.
CPU 1 holds lock B.
CPU 2 attempts lock B, becomes the pending waiter for B.
CPU 0 attempts lock B. B has locked+pending bits set, thus CPU 0 queues.
CPU 1 attempts lock A.
CPU 0 detects an ABBA deadlock.

Once deadlock detection happens for CPU 0, it will sit waiting for the
next waiter in the queue to populate node->next, which will experience
delays until such a waiter arrives.

Fix this by adjusting the logic for the check for deadlocks preceding
the waitq_timeout label. It would make sense to consolidate code for
both cases and use 'ret' to distinguish the value being propagated, but
that is left as an exercise for a future refactoring task to avoid diff
noise in this patch.

Fixes: 7bd6e5ce5b ("rqspinlock: Disable queue destruction for deadlocks")
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260802021759.1139457-1-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
2026-08-06 16:32:42 -07:00