<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/fs/btrfs/inode.c, branch linux-7.2.y</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-7.2.y</id>
<link rel='self' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=linux-7.2.y'/>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2026-08-06T20:29:15+00:00</updated>
<entry>
<title>Merge tag 'for-7.2-rc6-fixup-worker-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux</title>
<updated>2026-08-06T20:29:15+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-08-06T20:29:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=6c68fa601b49683ecb04eded993a71dfa8b2ba0b'/>
<id>urn:sha1:6c68fa601b49683ecb04eded993a71dfa8b2ba0b</id>
<content type='text'>
Pull Btrfs Fixes 2: Electric Boogaloo from David Sterba:
 "This brings back the fixup worker infrastructure.

  It's a mechanism to detect pages/folios that are marked dirty without
  filesystem knowledge and require COW fixup. The consequence of not
  doing so is silent data loss.

  The first patch covers the scenarios in detail, also reflecting folio
  API port and subpage block size support added in recent years. The
  original fixup worker was only for pages.

  The patch is relatively big, half of the code is debugging and support
  code, the rest is the core design around the detection and fix.

  The second patch handles an unlikely case when there's work left
  during unmount"

* tag 'for-7.2-rc6-fixup-worker-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: flush the fixup workers during close_ctree
  btrfs: trigger cow fixup via dirty_folio()
</content>
</entry>
<entry>
<title>Merge tag 'for-7.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux</title>
<updated>2026-08-06T20:24:40+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-08-06T20:24:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=63354634885c8d41675c5af54f757db2d14326e6'/>
<id>urn:sha1:63354634885c8d41675c5af54f757db2d14326e6</id>
<content type='text'>
Pull btrfs fixes from David Sterba:

 - fix leak in encoded ioctl write

 - disable large folios on systems with highmem

 - disable block size &gt; page size when there's no transparent hugepage
   support (under experimental config)

 - reject compressed inline extents without valid LZO headers

 - properly initialize cached inode mapping (if block size &gt; page size)

* tag 'for-7.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: initialize inode mapping flags for cached inodes
  btrfs: disable bs &gt; ps support if no transparent hugepage support
  btrfs: fix memory leak in btrfs_do_encoded_write()
  btrfs: lzo: reject inline extents without valid headers
  btrfs: disable large folios for systems with highmem
</content>
</entry>
<entry>
<title>btrfs: flush the fixup workers during close_ctree</title>
<updated>2026-08-03T22:59:16+00:00</updated>
<author>
<name>Boris Burkov</name>
<email>boris@bur.io</email>
</author>
<published>2026-07-30T16:38:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ae2567b11c3df43861d05f856bdb3434b3961aa1'/>
<id>urn:sha1:ae2567b11c3df43861d05f856bdb3434b3961aa1</id>
<content type='text'>
Reintroducing the COW fixup worker brought back the unmount race fixed
by commit 41fd1e94066a ("btrfs: wait for fixup workers before stopping
cleaner kthread during umount") without bringing back the fix.

A fixup work item queued by the final writeback pass can still be in flight
when close_ctree() stops the cleaner kthread and frees the fs roots.
While destroy_workqueue() drains the queue, that happens after the
cleaner thread was freed, so btrfs_add_delayed_iput() called from the
fixup worker is no longer safe (not to mention that we are already in
BTRFS_FS_STATE_NO_DELAYED_IPUT when it runs).

Therefore we need to bring back explicitly flushing the fixup workqueue
as in Filipe's original fix. The first flush will catch all the fixup
writeback queued during the final sync before umount, but some of that
might hit memory allocation errors and stay fixup in the blocks/folio,
leading any subsequent writeback triggered *inside* umount (e.g. reclaim
workers shutting down) to hit it and queue again. To fix that, and the
possibility of any really long-lived pinned folios getting marked, deny
queueing new fixup during umount. That allows us to flush twice (once
before doing a real writeback pass to get the actual data, second time
to clean up any rather unlikely stragglers right before declaring
BTRFS_FS_STATE_NO_DELAYED_IPUT) and be certain nothing got re-queued.

Reproduced by injecting a one-shot 30s sleep at the head of
btrfs_writepage_fixup_worker() on a KASAN kernel, running the normal
reproducing read dio workload before unmount and then observing:

  BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x35/0x50
  Read of size 1 at addr ffff88810b4b08f8 by task kworker/u32:5/219
  Workqueue: btrfs-fixup btrfs_writepage_fixup_worker [btrfs]
  Call Trace:
   _raw_spin_lock_irqsave+0x35/0x50
   try_to_wake_up+0xc0/0x18c0
   btrfs_writepage_fixup_worker+0x7f3/0xf20 [btrfs]
  ...

Fixes: 4be9c7da6860 ("btrfs: trigger cow fixup via dirty_folio()")
Assisted-by: LLM (reproduction, analysis)
Reviewed-by: Qu Wenruo &lt;wqu@suse.com&gt;
Signed-off-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: initialize inode mapping flags for cached inodes</title>
<updated>2026-07-31T14:56:05+00:00</updated>
<author>
<name>Qu Wenruo</name>
<email>wqu@suse.com</email>
</author>
<published>2026-07-31T00:44:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=0ef349734a93227b45f65fc50a3311d1cc5f03e9'/>
<id>urn:sha1:0ef349734a93227b45f65fc50a3311d1cc5f03e9</id>
<content type='text'>
[BUG]
When running generic/795 with 8K block size, 4K page size, the test
always fails, triggering some ASSERT()s related to folio size:

  795 (241074): drop_caches: 3
  assertion failed: IS_ALIGNED(start, blocksize) &amp;&amp; IS_ALIGNED(end + 1, blocksize), in extent_io.c:1404 (blocksize=8192 root=262 ino=258 start=16826368 end=16830463 mapping min order=0)
  ------------[ cut here ]------------
  kernel BUG at extent_io.c:1404!
  Oops: invalid opcode: 0000 [#1] SMP
  CPU: 8 UID: 0 PID: 241105 Comm: fsstress Tainted: G           OE       7.2.0-rc5-custom+ #442 PREEMPT(full)  f4bfb352566f3949f29c233ce6f735050a03b245
  Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
  RIP: 0010:assert_folio_range.cold+0x3d/0x3f [btrfs]
  Call Trace:
   &lt;TASK&gt;
   btrfs_read_folio+0x9e/0x170 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
   prepare_one_folio.constprop.0+0x104/0x2a0 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
   btrfs_buffered_write+0x285/0xa50 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
   btrfs_do_write_iter+0x1aa/0x210 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
   iter_file_splice_write+0x31a/0x540
   direct_splice_actor+0x53/0x170
   splice_direct_to_actor+0xe9/0x240
   do_splice_direct+0x76/0xb0
   vfs_copy_file_range+0x1fd/0x630
   __x64_sys_copy_file_range+0xf9/0x220
   do_syscall_64+0xe1/0x790
   entry_SYSCALL_64_after_hwframe+0x4b/0x53
   &lt;/TASK&gt;
  ---[ end trace 0000000000000000 ]---

The ASSERT() itself is added by a later patch.
The crash is triggered with that new debug patch, and without this fix.

[CAUSE]
In the above case, the start 16826368 is properly 8K aligned, but the
end (16830463 + 1) is not 8K aligned.
Furthermore the mapping's minimal folio order is 0, not the expected 1
for 8K block size with 4K page size.

So this means some inodes do not have btrfs_set_inode_mapping_order()
called on it.

The missing btrfs_set_inode_mapping_order() call happens for cached
inodes, through the following events:

- btrfs_create_new_inode() called for inode X
  Which properly sets minimal folio order for the VFS inode.

- btrfs_update_inode() called for inode X
  Which calls btrfs_delayed_update_inode() to create a delayed_node
  into root-&gt;delayed_nodes xarray.

- Drop cache/memory pressure, evicting in-memory inode X
  Which evicted the inode X, but delayed_node is still in
  root-&gt;delayed_nodes for future reuse.

- btrfs_iget() for inode X called again

  btrfs_iget()
  |- btrfs_iget_locked()
  |  |- iget5_locked_rcu()
  |     Which creates a new vfs_inode for btrfs, whose mapping still
  |     has the minimal order as 0.
  |
  |- btrfs_read_locked_inode()
     |- btrfs_fill_inode()
     |  |- btrfs_get_delayed_node()
     |     Which found out the previous node, and use that delayed
     |     node to initialize the new inode.
     |
     |- filled = true;
     |- if (filled) goto cache_index;
        Which skips the btrfs_update_inode_mapping_flags() and
	btrfs_set_inode_mapping_order() calls.
	So the inode still has minimal folio order set as 0, not
	the required 1.

Thus later page cache read will get a folio whose size is smaller than
block size, as the mapping has its minimal folio order set as 0 not 1,
then trigger the ASSERT().

[FIX]
Move the btrfs_update_inode_mapping_flags() and
btrfs_set_inode_mapping_order() calls under cache_index label,
so that the mapping flags and minimal folio order is always set
no matter if we have a cached inode.

Assisted-by: LLM (analysis)
Fixes: ecde48a1a6b3 ("btrfs: expose per-inode stable writes flag")
Fixes: cc38d178ff33 ("btrfs: enable large data folio support under CONFIG_BTRFS_EXPERIMENTAL")
Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Qu Wenruo &lt;wqu@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: fix memory leak in btrfs_do_encoded_write()</title>
<updated>2026-07-31T14:55:11+00:00</updated>
<author>
<name>Dmitry Antipov</name>
<email>dmantipov@yandex.ru</email>
</author>
<published>2026-07-27T11:53:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=d2a4e4e626b2f4670b69b430c357f03f53eb6632'/>
<id>urn:sha1:d2a4e4e626b2f4670b69b430c357f03f53eb6632</id>
<content type='text'>
Local fuzzing of 6.12.94 has found the following memory leak:

Unreferenced object 0xffff888018050a80 (size 64):
  comm "syz.0.17", pid 10297, jiffies 4294953601
  hex dump (first 32 bytes):
    00 10 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
    10 0a 05 18 80 88 ff ff 10 0a 05 18 80 88 ff ff  ................
  backtrace (crc a8a6fc29):
    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
    slab_post_alloc_hook mm/slub.c:4152 [inline]
    slab_alloc_node mm/slub.c:4197 [inline]
    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
    kmalloc_noprof include/linux/slab.h:878 [inline]
    extent_changeset_alloc fs/btrfs/extent_io.h:207 [inline]
    qgroup_reserve_data+0x1c5/0x7d0 fs/btrfs/qgroup.c:4305
    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
    vfs_ioctl fs/ioctl.c:51 [inline]
    __do_sys_ioctl fs/ioctl.c:906 [inline]
    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

Unreferenced object 0xffff888018050a00 (size 64):
  comm "syz.0.17", pid 10297, jiffies 4294953601
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 ff 0f 00 00 00 00 00 00  ................
    90 0a 05 18 80 88 ff ff 90 0a 05 18 80 88 ff ff  ................
  backtrace (crc cb5c9580):
    kmemleak_alloc_recursive include/linux/kmemleak.h:42 [inline]
    slab_post_alloc_hook mm/slub.c:4152 [inline]
    slab_alloc_node mm/slub.c:4197 [inline]
    __kmalloc_cache_noprof+0x168/0x2c0 mm/slub.c:4358
    kmalloc_noprof include/linux/slab.h:878 [inline]
    kzalloc_noprof include/linux/slab.h:1014 [inline]
    ulist_prealloc+0x9c/0x110 fs/btrfs/ulist.c:114
    extent_changeset_prealloc fs/btrfs/extent_io.h:217 [inline]
    __set_extent_bit+0x16b/0x1a70 fs/btrfs/extent-io-tree.c:1086
    set_record_extent_bits+0x50/0x90 fs/btrfs/extent-io-tree.c:1821
    qgroup_reserve_data+0x274/0x7d0 fs/btrfs/qgroup.c:4312
    btrfs_qgroup_reserve_data+0x2e/0xb0 fs/btrfs/qgroup.c:4355
    btrfs_do_encoded_write+0x92e/0x1040 fs/btrfs/inode.c:9746
    btrfs_encoded_write fs/btrfs/file.c:1482 [inline]
    btrfs_do_write_iter+0x280/0x610 fs/btrfs/file.c:1507
    btrfs_ioctl_encoded_write+0x3d6/0x490 fs/btrfs/ioctl.c:4738
    btrfs_ioctl+0x6f9/0xc90 fs/btrfs/ioctl.c:-1
    vfs_ioctl fs/ioctl.c:51 [inline]
    __do_sys_ioctl fs/ioctl.c:906 [inline]
    __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:892
    do_syscall_x64 arch/x86/entry/common.c:47 [inline]
    do_syscall_64+0xbe/0x1a0 arch/x86/entry/common.c:78
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

Fix this by freeing an extent changeset before returning from
btrfs_do_encoded_write().

Fixes: 7c0c7269f7b5 ("btrfs: add BTRFS_IOC_ENCODED_WRITE")
Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Dmitry Antipov &lt;dmantipov@yandex.ru&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: trigger cow fixup via dirty_folio()</title>
<updated>2026-07-30T17:28:36+00:00</updated>
<author>
<name>Boris Burkov</name>
<email>boris@bur.io</email>
</author>
<published>2026-07-27T22:23:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=0680cbbf39ca61c70be16141b5259f822e7cdb3b'/>
<id>urn:sha1:0680cbbf39ca61c70be16141b5259f822e7cdb3b</id>
<content type='text'>
The problem scenario:
If we have a folio mmapped shared and then somebody does a dio read with
that folio as the read destination, then it is possible that the dio
will see a dirty destination page when it starts (and thus skip
dirtying and just GUP pin it) but then while it is doing the read, btrfs
finishes writing it back and by the endio, the folio is clean. In that
case, the dio read must re-dirty the folio with aops-&gt;dirty_folio():

btrfs_check_read_bio()
|- __iomap_dio_bio_end_io() from btrfs_bio_end_io()
   |- bio_check_pages_dirty()
      |- bio_dirty_fn()
         |- bio_release_pages(bio, true)
            |- __bio_release_pages(bio, mark_dirty == true)
               |- folio_lock()
               |- folio_mark_dirty()
                  |- aops-&gt;dirty_folio()
               |- folio_unlock()

A data block normally moves through writeback as follows:

  TASK
    folio_lock
    write              clean -&gt; dirty bit + delalloc
    folio_unlock
  WRITEBACK
    for-each-dirty-folio:
      folio_lock
      run_delalloc     delalloc consumed  -&gt; dirty bit + OE
      submission       dirty bit consumed -&gt; writeback bit + OE
      folio_unlock
  ENDIO
    endio              OE bytes accounted
    OE finish          writeback -&gt; clean; destroy OE

Three critical invariants that this path maintains are:

  I1. Any dirty block is covered by delalloc xor an ordered extent
  I2. Any dirty block covered by an OE will be submitted into that OE
  I3. Any dirty block already submitted into an OE will not be submitted
      again into the same OE.

These ensure that the block will be written exactly once. It is clear
that not reserving delalloc for the re-dirty case violates I1.

This situation, even without bs &lt; folio_size, has long required btrfs to
fixup such dirty pages during writeback with an asynchronous worker that
is allowed to do this expensive work and writeback does not proceed for
a folio while it is doing this work.

Commit 247e743cbe6e ("Btrfs: Use async helpers to deal with pages that
have been improperly dirtied") introduced the COW fixup to catch exactly
this class at writeback, way back in 2008.

Since then, there have been many advances to prevent most of the causes
of such re-dirtying and we thought we could get away with removing the
annoying cow-fixup in the hope of simplifying writeback for large folio
support.

  Commit b2a9f217ad3f ("btrfs: remove the COW fixup mechanism")
  Commit 4927b141877c ("btrfs: remove folio ordered flag and subpage bitmap")

Since it turns out this assumption was incorrect, as evidenced by the
report and attendant reproducers, we must reintroduce the fixup concept.

This is of course critically further complicated by bs &lt; folio_size. In
that case, rather than just a folio dirty bit, we have a bitmap for the
dirty blocks in the folio. And the (also broken) invariant is:

  I4. folio dirty IFF at least one block bitmap dirty.

The original report of a stall on a misinterpreted empty bitmap is
exactly evidence of a violation of I4.

It is exactly because of bs &lt; folio_size we don't want to simply revert the
removal patches. The original fixup was not properly bs &lt; folio_size
aware, which motivated removal in the first place. So we wish to build a
bs &lt; folio_size aware fixup.

One other important detail from the old design, any normal write that
happens after a re-dirty but before a fixup is racing with the cow fixup
to do the delalloc reservation, therefore it must cancel the fixup state.
If it arrives after the reservation exists, it will be a normal dirty
overwrite. This critically informs the design in a pretty clear way.
fixup requiring re-dirty has folio granularity, while cancellation has
delalloc (block) granularity so while we only ever produce fixup in
chunks of folios, we must be able to clear it in blocks. Therefore we
must track the blocks needing fixup at block granularity.

The obvious way to do this is with a new bitmap in btrfs_folio_state,
but it is desirable to avoid that if possible. Unfortunately, I don't
think it is possible and the reason is subtle and leans on a sort of
extreme reproducer, but I think can be explained relatively succinctly.

Consider a folio whose two halves will land in different ordered extents
(can be accomplished with tricks using nodatasum) and a dio read is
running with it as the shared mmap destination.

1. The front half:
   a. folio comes clean on a normal write
   b. dio read completes into the folio marking it fixup.
   c. a write comes for the previous folio for a range extending into
      this folio, this is a cancellation of the fixup which reserves
      space.
   d. writeback runs on the range *not* overlapping the folio. This half
      remains dirty but is now covered by an OE and is awaiting
      writeback running on its range to be submitted and finish the OE.

2. The back half:
   a. the folio is part of an OE that gets far enough along to clear
      writeback.
   b. dio read completes into the folio marking it fixup.

After this, the folio's front half is dirty in the "normal" sense, it
needs to be submitted to the OE waiting for it. It's a cancelled fixup.
Meanwhile, the second half is a true fresh fixup. So at this point if we
run writeback on this folio, we genuinely can't know what to do without
block level information. If we submit it, we submit unreserved dirty
from the back half. If we don't, we will never finish the OE waiting for
it. So it's either a corruption or a deadlock.

Thus, the full high level design picture:

- btrfs_data_dirty_folio(): For out of band non-reserving dirties,
  mark still-clean blocks inside EOF dirty and set their fixup bits
  (the event carries no range, so every clean block is suspect).
  Already-dirty blocks are covered or pending and are left alone.

- Writeback: skip fixup blocks and enqueue work for them

- writepage_fixup(): for each fixup block do the fixup reservation in a
  worker, after which the blocks can be written back normally.

- Typical reserving write paths cancel fixup state for the ranges they
  cover with btrfs_folio_cancel_fixup()

Link: https://lore.kernel.org/linux-btrfs/20260721191152.101118-1-borntraeger@linux.ibm.com/
Assisted-by: LLM
Reviewed-by: Qu Wenruo &lt;wqu@suse.com&gt;
Signed-off-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>Merge tag 'for-7.2-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux</title>
<updated>2026-07-21T15:06:24+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-07-21T15:06:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=51f247c4b293b470723e69a321e2cc5ecf9080db'/>
<id>urn:sha1:51f247c4b293b470723e69a321e2cc5ecf9080db</id>
<content type='text'>
Pull btrfs fixes from David Sterba:
 "I'm catching up with the fix backlog in the development branch, so
  here's a number of them and will probably send one more for this or
  the next rc:

   - relocation fixes:
     - skip attempting compression on reloc inodes
     - exclude inline extents from file extent offset checks
     - fix minor memory leak after error when adding reloc root
     - fix root cleanup after inserting and merging

   - fix clearing folio tags after writeback

   - clear logging flag of extent map before splitting

   - fix unsigned 32/64 type conversions when accounting dirty metadata,
     leading to continually exceeding threshold

   - fix regression in 32bit compat ioctl for subvolume info

   - fix type of SEARCH_TREE ioctl buffer in UAPI header

   - fix expression in ASSERT expression which can be unconditionally
     evaluated on some compilers

   - only account delalloc bytes for regular inodes"

* tag 'for-7.2-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix GET_SUBVOL_INFO after compat refactor
  btrfs: free mapping node on duplicate reloc root insert
  btrfs: fix a regression where PAGECACHE_TAG_DIRTY is never cleared
  btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps
  btrfs: fix u32 to s64 type conversion in dirty_metadata_bytes accounting
  btrfs: fix NULL pointer deref during assertion in btrfs_backref_free_node()
  btrfs: only account delalloc bytes for regular file inodes in btrfs_getattr()
  btrfs: reject inline file extents item in get_new_location()
  btrfs: do not try compression for data reloc inodes
  btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8
  btrfs: fix reloc root cleanup in merge_reloc_roots()
  btrfs: fix use-after-free on reloc root after error in insert_dirty_subvol()
</content>
</entry>
<entry>
<title>btrfs: only account delalloc bytes for regular file inodes in btrfs_getattr()</title>
<updated>2026-07-14T05:03:26+00:00</updated>
<author>
<name>Dave Chen</name>
<email>davechen@synology.com</email>
</author>
<published>2026-06-26T06:45:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9411aafdf352b8d72668732af5a37dcb27383e25'/>
<id>urn:sha1:9411aafdf352b8d72668732af5a37dcb27383e25</id>
<content type='text'>
btrfs_getattr() unconditionally reads BTRFS_I(inode)-&gt;new_delalloc_bytes
and adds it (sector-aligned) to stat-&gt;blocks for every inode type.
However, new_delalloc_bytes lives in a union with last_dir_index_offset:

    union {
        u64 new_delalloc_bytes;     /* files only */
        u64 last_dir_index_offset;  /* directories only */
    };

For a directory inode this memory holds last_dir_index_offset, which is
set during directory logging (e.g. flush_dir_items_batch()) to the
offset of the last logged BTRFS_DIR_INDEX_KEY.  That offset grows with
the number of entries ever created in the directory (dir indexes are
monotonic and never reused), so it can be arbitrarily large.

As a result, after a directory has been logged (e.g. via an fsync that
triggers directory logging), btrfs_getattr() reports inflated st_blocks
for that directory.  The inflation is purely in-core and disappears
after the inode is evicted and reloaded (btrfs_alloc_inode() zeroes the
union), e.g. after a remount.

Reproducer (on a btrfs filesystem):

    D=/mnt/btrfs/d
    mkdir -p $D
    for i in $(seq 1 20000); do touch $D/f$i; done
    sync                      # commit, push dir index high
    touch $D/trigger          # dirty the dir in a new transaction
    xfs_io -c fsync $D        # log the directory -&gt; sets last_dir_index_offset
    stat -c '%b' $D           # st_blocks is now inflated (e.g. 40)
    # umount + mount -&gt; st_blocks drops back to the correct value

The evict path already knows this union is type-dependent and guards the
corresponding WARN_ON with !S_ISDIR() in btrfs_destroy_inode(); only
btrfs_getattr() was missing the equivalent check.

Only read new_delalloc_bytes for regular files, which are the only
inodes that ever set it.

Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Dave Chen &lt;davechen@synology.com&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>Merge tag 'for-7.2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux</title>
<updated>2026-06-16T06:38:02+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-06-16T06:38:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=31b706da2cfd8ee3352391181ccf9696bed3d25d'/>
<id>urn:sha1:31b706da2cfd8ee3352391181ccf9696bed3d25d</id>
<content type='text'>
Pull btrfs updates from David Sterba:
 "The most noticeable change is to enable large folios by default, it's
  been in testing for a few releases. Related to that is huge folio
  support (still under experimental config). Otherwise a few ioctl
  updates, performance improvements and usual fixes and core changes.

  User visible changes:

   - enable large folios by default, added in 6.17 (under experimental
     build), no feature limitations, a big change internally

   - new ioctl to return raw checksums to userspace (a bit tricky given
     compression and tail extents), can be used for mkfs and
     deduplication optimizations

   - provide stable UUID for e.g. overlayfs and temp_fsid, also
     reflected in statvfs() field f_fsid, internal dev_t is hashed in to
     allow cloning

   - add 32bit compat version of GET_SUBVOL_INFO ioctl

   - in experimental build, support huge folios (up to 2M)

  Performance related improvements/changes:

   - limit bio size to the estimated optimum derived from the queue,
     this prevents build up of too much data for writeback, which could
     cause latency spikes (reported improvement 15% on sequential
     writes)

   - don't force direct IO to be serialized, forgotten change during
     mount API port, brings back +60% of throughput

   - lockless calculation of number of shrinkable extent maps, improve
     performance with many memcg allocated objects

  Notable fixes:

   - in zoned mode, fix a deadlock due to zone reclaim and relocation
     when space needs to be flushed

   - don't trim device which is internally not tracked as writeable
     (e.g. when missing device is being rescanned)

   - fix deadlock when cloning inline extent and mounted with
     flushoncommit

   - fix false IO failures after direct IO falls back to buffered write
     in some cases

  Core:

   - remove COW fixup mechanism completely; detect and fix changes to
     pages outside of filesystem tracking, guaranteed since 5.8, grace
     period is over

   - remove 2K block size support, experimental to test subpage code on
     x86_64 but now it would block folio changes

   - tree-checker improvements of:
      - free-space cache and tree items
      - root reference and backref items
      - extent state exceptions in reloc tree

   - subpage mode updates:
      - code optimizations, simplify tracking bitmaps
      - re-enable readahead of compressed extent
      - extend bitmap size to cover huge folios

   - add tracepoints related to sync, tree-log and transactions

   - device stats item tracking unification, remove item if there are no
     stats recorded, also don't leave stale stats on replaced device

   - allow extent buffer pages to be allocated as movable, to help page
     migration

   - added checks for proper extent buffer release

   - btrfs.ko code size reduction due to transaction abort call
     simplifications

   - several struct size reductions

   - more auto free conversions

   - more verbose assertions"

* tag 'for-7.2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (130 commits)
  btrfs: fix use-after-free after relocation failure with concurrent COW
  btrfs: move WARN_ON on unexpected error in __add_tree_block()
  btrfs: move locking into btrfs_get_reloc_bg_bytenr()
  btrfs: lzo: reject compressed segment that overflows the compressed input
  btrfs: retry faulting in the pages after a zero sized short direct write
  btrfs: fix incorrect buffered IO fallback for append direct writes
  btrfs: fix false IO failure after falling back to buffered write
  btrfs: use verbose assertions in backref.c
  btrfs: print a message when a missing device re-appears
  btrfs: do not trim a device which is not writeable
  btrfs: return real error after lookup failure in btrfs_ioctl_default_subvol()
  btrfs: use mapping shared locking for reading super block
  btrfs: use lockless read in nr_cached_objects shrinker callback
  btrfs: switch local indicator variables to bools
  btrfs: send: pass bool for pending_move and refs_processed parameters
  btrfs: use shifts for sectorsize and nodesize
  btrfs: fix deadlock cloning inline extent when using flushoncommit
  btrfs: allocate eb-attached btree pages as movable
  btrfs: add 32-bit compat ioctl for BTRFS_IOC_GET_SUBVOL_INFO
  btrfs: derive f_fsid from on-disk fsid and dev_t
  ...
</content>
</entry>
<entry>
<title>Merge tag 'vfs-7.2-rc1.inode' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs</title>
<updated>2026-06-14T21:14:23+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2026-06-14T21:14:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=fac863c887a05d7c3091c5eccf30c89c2116ae11'/>
<id>urn:sha1:fac863c887a05d7c3091c5eccf30c89c2116ae11</id>
<content type='text'>
Pull vfs inode updates from Christian Brauner:
 "This extends the lockless -&gt;i_count handling.

  iput() could already decrement any value greater than one locklessly
  but acquiring a reference always required taking inode-&gt;i_lock. Now
  acquiring a reference is lockless as long as the count was already at
  least 1, i.e., only the 0-&gt;1 and 1-&gt;0 transitions take the lock.

  This avoids the lock for the common cases of nfs calling into the
  inode hash and btrfs using igrab(). Cleanup-wise icount_read_once() is
  added to line up with inode_state_read_once() and the open-coded
  -&gt;i_count loads across the tree are converted, and ihold() is
  relocated and tidied up.

  On top of that some stale lock ordering annotations are retired from
  the inode hash code: iunique() no longer takes the hash lock since the
  inode hash became RCU-searchable and s_inode_list_lock is no longer
  taken under the hash lock either"

* tag 'vfs-7.2-rc1.inode' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fs: retire stale lock ordering annotations from inode hash
  fs: allow lockless -&gt;i_count bumps as long as it does not transition 0-&gt;1
  fs: relocate and tidy up ihold()
  fs: add icount_read_once() and stop open-coding -&gt;i_count loads
</content>
</entry>
</feed>
