* [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
@ 2025-11-26 14:23 kernel test robot
2025-12-02 0:51 ` Leo Martins
0 siblings, 1 reply; 9+ messages in thread
From: kernel test robot @ 2025-11-26 14:23 UTC (permalink / raw)
To: Leo Martins
Cc: oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs, oliver.sang
Hello,
kernel test robot noticed "addition_on#;use-after-free" on:
commit: e8513c012de75fd65e2df5499572bc6ef3f6e409 ("btrfs: implement ref_tracker for delayed_nodes")
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
[test failed on linus/master 30f09200cc4aefbd8385b01e41bde2e4565a6f0e]
[test failed on linux-next/master 92fd6e84175befa1775e5c0ab682938eca27c0b2]
in testcase: blogbench
version: blogbench-x86_64-1.2-1_20251009
with following parameters:
disk: 1SSD
fs: btrfs
cpufreq_governor: performance
config: x86_64-rhel-9.4
compiler: gcc-14
test machine: 192 threads 4 sockets Intel(R) Xeon(R) Platinum 9242 CPU @ 2.30GHz (Cascade Lake) with 176G memory
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
[ 92.359770][ T1319] ------------[ cut here ]------------
[ 92.365399][ T2115] 1513 283338 42318 194834 39930 140043 83712
[ 92.365683][ T1319] refcount_t: addition on 0; use-after-free.
[ 92.371060][ T2115]
[ 92.381336][ T1319] WARNING: CPU: 29 PID: 1319 at lib/refcount.c:25 refcount_warn_saturate (lib/refcount.c:25 (discriminator 1))
[ 92.389049][ T2115] 2174 291211 39936 202785 36246 141919 76774
[ 92.389356][ T1319] Modules linked in:
[ 92.398571][ T2115]
[ 92.419599][ T1319] dm_mod intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp btrfs kvm_intel blake2b_generic xor kvm raid6_pq snd_pcm irqbypass ipmi_ssif snd_timer ghash_clmulni_intel ahci ast rapl snd intel_cstate libahci acpi_power_meter nvme drm_client_lib binfmt_misc drm_shmem_helper mei_me soundcore intel_uncore ioatdma ipmi_si i2c_i801 pcspkr nvme_core acpi_ipmi libata mei drm_kms_helper i2c_smbus lpc_ich intel_pch_thermal dca ipmi_devintf wmi ipmi_msghandler acpi_pad joydev drm fuse nfnetlink
[ 92.477068][ T1319] CPU: 29 UID: 0 PID: 1319 Comm: kworker/u770:33 Tainted: G S 6.17.0-rc7-00022-ge8513c012de7 #1 VOLUNTARY
[ 92.490808][ T1319] Tainted: [S]=CPU_OUT_OF_SPEC
[ 92.495958][ T1319] Hardware name: Intel Corporation ............/S9200WKBRD2, BIOS SE5C620.86B.0D.01.0552.060220191912 06/02/2019
[ 92.508765][ T1319] Workqueue: btrfs-endio-write btrfs_work_helper [btrfs]
[ 92.516545][ T1319] RIP: 0010:refcount_warn_saturate (lib/refcount.c:25 (discriminator 1))
[ 92.523057][ T1319] Code: 95 95 ff 0f 0b e9 4b 45 90 00 80 3d d3 40 98 01 00 0f 85 5e ff ff ff 48 c7 c7 88 fe ad 82 c6 05 bf 40 98 01 01 e8 9b 95 95 ff <0f> 0b c3 cc cc cc cc 48 c7 c7 e0 fe ad 82 c6 05 a3 40 98 01 01 e8
All code
========
0: 95 xchg %eax,%ebp
1: 95 xchg %eax,%ebp
2: ff 0f decl (%rdi)
4: 0b e9 or %ecx,%ebp
6: 4b rex.WXB
7: 45 90 rex.RB xchg %eax,%r8d
9: 00 80 3d d3 40 98 add %al,-0x67bf2cc3(%rax)
f: 01 00 add %eax,(%rax)
11: 0f 85 5e ff ff ff jne 0xffffffffffffff75
17: 48 c7 c7 88 fe ad 82 mov $0xffffffff82adfe88,%rdi
1e: c6 05 bf 40 98 01 01 movb $0x1,0x19840bf(%rip) # 0x19840e4
25: e8 9b 95 95 ff call 0xffffffffff9595c5
2a:* 0f 0b ud2 <-- trapping instruction
2c: c3 ret
2d: cc int3
2e: cc int3
2f: cc int3
30: cc int3
31: 48 c7 c7 e0 fe ad 82 mov $0xffffffff82adfee0,%rdi
38: c6 05 a3 40 98 01 01 movb $0x1,0x19840a3(%rip) # 0x19840e2
3f: e8 .byte 0xe8
Code starting with the faulting instruction
===========================================
0: 0f 0b ud2
2: c3 ret
3: cc int3
4: cc int3
5: cc int3
6: cc int3
7: 48 c7 c7 e0 fe ad 82 mov $0xffffffff82adfee0,%rdi
e: c6 05 a3 40 98 01 01 movb $0x1,0x19840a3(%rip) # 0x19840b8
15: e8 .byte 0xe8
[ 92.543676][ T1319] RSP: 0018:ffffc9000fcabca0 EFLAGS: 00010282
[ 92.550187][ T1319] RAX: 0000000000000000 RBX: ffff888e3d2c8d68 RCX: 0000000000000000
[ 92.558625][ T1319] RDX: ffff88984f36a3c0 RSI: 0000000000000001 RDI: ffff88984f35c200
[ 92.567066][ T1319] RBP: ffff8881069c6368 R08: 00000000000008fd R09: 000000000000001d
[ 92.575508][ T1319] R10: 5b5d393933353633 R11: 205d353131325420 R12: ffff888cd91ced20
[ 92.583960][ T1319] R13: 0000000000081087 R14: ffff888ed98c2ba8 R15: ffff8881069c6000
[ 92.592397][ T1319] FS: 0000000000000000(0000) GS:ffff8898cb53c000(0000) knlGS:0000000000000000
[ 92.601843][ T1319] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 92.608920][ T1319] CR2: 0000000000000800 CR3: 0000002c7de24001 CR4: 00000000007726f0
[ 92.617398][ T1319] PKRU: 55555554
[ 92.621442][ T1319] Call Trace:
[ 92.625216][ T1319] <TASK>
[ 92.628645][ T1319] btrfs_get_delayed_node+0xda/0x1b0 btrfs
[ 92.636027][ T1319] btrfs_get_or_create_delayed_node+0x12a/0x1b0 btrfs
[ 92.644356][ T1319] btrfs_delayed_update_inode (fs/btrfs/delayed-inode.c:1957) btrfs
[ 92.651387][ T1319] ? btrfs_update_root_times (fs/btrfs/root-tree.c:488) btrfs
[ 92.658201][ T1319] btrfs_update_inode (fs/btrfs/inode.c:4174) btrfs
[ 92.664431][ T1319] btrfs_finish_one_ordered (fs/btrfs/inode.c:4188 fs/btrfs/inode.c:3226) btrfs
[ 92.671351][ T1319] btrfs_work_helper (fs/btrfs/async-thread.c:313) btrfs
[ 92.677606][ T1319] process_one_work (arch/x86/include/asm/jump_label.h:36 include/trace/events/workqueue.h:110 kernel/workqueue.c:3241)
[ 92.682972][ T1319] worker_thread (kernel/workqueue.c:3313 (discriminator 2) kernel/workqueue.c:3400 (discriminator 2))
[ 92.688065][ T1319] ? __pfx_worker_thread (kernel/workqueue.c:3346)
[ 92.693679][ T1319] kthread (kernel/kthread.c:463)
[ 92.698145][ T1319] ? __pfx_kthread (kernel/kthread.c:412)
[ 92.703205][ T1319] ret_from_fork (arch/x86/kernel/process.c:148)
[ 92.708102][ T1319] ? __pfx_kthread (kernel/kthread.c:412)
[ 92.713169][ T1319] ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
[ 92.718420][ T1319] </TASK>
[ 92.721904][ T1319] ---[ end trace 0000000000000000 ]---
[ 92.772617][ T2117] [ perf record: Woken up 232 times to write data ]
[ 92.772626][ T2117]
[ 97.041836][ T2115] 2696 307116 30435 210930 28018 143529 49252
[ 97.041848][ T2115]
[ 107.042097][ T2115] 3311 309408 37927 214378 34672 141593 71871
[ 107.042111][ T2115]
[ 107.492140][ T2117] Warning:
[ 107.492150][ T2117]
[ 107.504083][ T2117] 174 out of order events recorded.
[ 107.504089][ T2117]
[ 107.572544][ T2117] [ perf record: Captured and wrote 680.421 MB /tmp/lkp/perf-sched.data (2685986 samples) ]
[ 107.572552][ T2117]
[ 116.735824][ C3] perf: interrupt took too long (2518 > 2500), lowering kernel.perf_event_max_sample_rate to 79000
[ 116.747160][ C3] perf: interrupt took too long (3163 > 3147), lowering kernel.perf_event_max_sample_rate to 63000
[ 116.760698][ T2117] Events enabled
[ 116.760708][ T2117]
[ 116.763935][ C3] perf: interrupt took too long (3955 > 3953), lowering kernel.perf_event_max_sample_rate to 50000
[ 116.796549][ C67] perf: interrupt took too long (4953 > 4943), lowering kernel.perf_event_max_sample_rate to 40000
[ 116.866088][ C131] perf: interrupt took too long (6210 > 6191), lowering kernel.perf_event_max_sample_rate to 32000
[ 117.042049][ T2115] 3836 310809 30767 213835 28646 137339 48846
[ 117.042057][ T2115]
[ 117.739156][ C25] perf: interrupt took too long (7763 > 7762), lowering kernel.perf_event_max_sample_rate to 25000
[ 119.838008][ T2117] [ perf record: Woken up 399 times to write data ]
[ 119.838018][ T2117]
[ 124.613970][ T2117] Warning:
[ 124.613980][ T2117]
[ 124.625324][ T2117] Processed 1601669 events and lost 6 chunks!
[ 124.625332][ T2117]
[ 124.635344][ T2117]
[ 124.635349][ T2117]
[ 124.642513][ T2117] Check IO/CPU overload!
[ 124.642518][ T2117]
[ 124.649994][ T2117]
[ 124.649999][ T2117]
[ 124.656077][ T2117] Warning:
[ 124.656082][ T2117]
[ 124.664342][ T2117] 35 out of order events recorded.
[ 124.664347][ T2117]
[ 124.678444][ T2117] [ perf record: Captured and wrote 252.317 MB /tmp/lkp/perf_c2c.data (1412807 samples) ]
[ 124.678450][ T2117]
[ 127.042332][ T2115] 4407 303071 35022 208647 31346 136630 47202
[ 127.042344][ T2115]
[ 137.042250][ T2115] 4943 299584 31810 208626 30129 128390 56528
[ 137.042263][ T2115]
[ 147.042441][ T2115] 5385 300009 27874 208644 24778 132677 46221
[ 147.042453][ T2115]
[ 157.042433][ T2115] 5910 307972 30431 216088 28665 137389 57696
[ 157.042445][ T2115]
[ 167.042628][ T2115] 6460 304663 35022 213949 31758 139786 62225
[ 167.042640][ T2115]
[ 177.042573][ T2115] 6967 307323 30606 213465 26983 141516 63168
[ 177.042587][ T2115]
[ 187.042733][ T2115] 7407 307075 26787 213546 24994 142923 41523
[ 187.042745][ T2115]
[ 197.042791][ T2115] 7927 308105 34190 214356 29643 140592 52914
[ 197.042803][ T2115]
[ 207.042918][ T2115] 8549 301948 38038 210474 34706 141120 67811
[ 207.042931][ T2115]
[ 217.042636][ T2115] 8955 297050 25135 208501 22518 135881 44260
[ 217.042648][ T2115]
[ 227.038865][ T2115] 9471 304296 32936 210610 29938 137844 62809
[ 227.038870][ T2115]
[ 237.038945][ T2115] 9964 305929 31628 213754 28012 141671 62429
[ 237.038951][ T2115]
[ 247.039008][ T2115] 10440 307726 30685 214830 28062 140111 62249
[ 247.039015][ T2115]
[ 257.039183][ T2115] 10802 292789 23345 205882 20689 138434 48453
[ 257.039188][ T2115]
[ 267.043497][ T2115] 11273 306881 30725 212403 27270 143693 60639
[ 267.043508][ T2115]
[ 277.043510][ T2115] 11797 302806 33279 211710 30071 142609 64344
[ 277.043519][ T2115]
[ 287.039432][ T2115] 12205 264441 24852 186434 24016 129256 56311
[ 287.039437][ T2115]
[ 297.043412][ T2115] 12673 310406 27331 217050 25960 146991 54571
[ 297.043421][ T2115]
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20251126/202511262228.6dda231e-lkp@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-11-26 14:23 [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free kernel test robot
@ 2025-12-02 0:51 ` Leo Martins
2025-12-02 8:40 ` Oliver Sang
0 siblings, 1 reply; 9+ messages in thread
From: Leo Martins @ 2025-12-02 0:51 UTC (permalink / raw)
To: kernel test robot; +Cc: oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Wed, 26 Nov 2025 22:23:21 +0800 kernel test robot <oliver.sang@intel.com> wrote:
>
>
> Hello,
>
> kernel test robot noticed "addition_on#;use-after-free" on:
>
> commit: e8513c012de75fd65e2df5499572bc6ef3f6e409 ("btrfs: implement ref_tracker for delayed_nodes")
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
>
> [test failed on linus/master 30f09200cc4aefbd8385b01e41bde2e4565a6f0e]
> [test failed on linux-next/master 92fd6e84175befa1775e5c0ab682938eca27c0b2]
>
> in testcase: blogbench
> version: blogbench-x86_64-1.2-1_20251009
> with following parameters:
>
> disk: 1SSD
> fs: btrfs
> cpufreq_governor: performance
>
>
>
> config: x86_64-rhel-9.4
> compiler: gcc-14
> test machine: 192 threads 4 sockets Intel(R) Xeon(R) Platinum 9242 CPU @ 2.30GHz (Cascade Lake) with 176G memory
>
> (please refer to attached dmesg/kmsg for entire log/backtrace)
>
>
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <oliver.sang@intel.com>
> | Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
>
>
> [ 92.359770][ T1319] ------------[ cut here ]------------
> [ 92.365399][ T2115] 1513 283338 42318 194834 39930 140043 83712
> [ 92.365683][ T1319] refcount_t: addition on 0; use-after-free.
> [ 92.371060][ T2115]
> [ 92.381336][ T1319] WARNING: CPU: 29 PID: 1319 at lib/refcount.c:25 refcount_warn_saturate (lib/refcount.c:25 (discriminator 1))
> [ 92.389049][ T2115] 2174 291211 39936 202785 36246 141919 76774
> [ 92.389356][ T1319] Modules linked in:
> [ 92.398571][ T2115]
> [ 92.419599][ T1319] dm_mod intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp btrfs kvm_intel blake2b_generic xor kvm raid6_pq snd_pcm irqbypass ipmi_ssif snd_timer ghash_clmulni_intel ahci ast rapl snd intel_cstate libahci acpi_power_meter nvme drm_client_lib binfmt_misc drm_shmem_helper mei_me soundcore intel_uncore ioatdma ipmi_si i2c_i801 pcspkr nvme_core acpi_ipmi libata mei drm_kms_helper i2c_smbus lpc_ich intel_pch_thermal dca ipmi_devintf wmi ipmi_msghandler acpi_pad joydev drm fuse nfnetlink
> [ 92.477068][ T1319] CPU: 29 UID: 0 PID: 1319 Comm: kworker/u770:33 Tainted: G S 6.17.0-rc7-00022-ge8513c012de7 #1 VOLUNTARY
> [ 92.490808][ T1319] Tainted: [S]=CPU_OUT_OF_SPEC
> [ 92.495958][ T1319] Hardware name: Intel Corporation ............/S9200WKBRD2, BIOS SE5C620.86B.0D.01.0552.060220191912 06/02/2019
> [ 92.508765][ T1319] Workqueue: btrfs-endio-write btrfs_work_helper [btrfs]
> [ 92.516545][ T1319] RIP: 0010:refcount_warn_saturate (lib/refcount.c:25 (discriminator 1))
> [ 92.523057][ T1319] Code: 95 95 ff 0f 0b e9 4b 45 90 00 80 3d d3 40 98 01 00 0f 85 5e ff ff ff 48 c7 c7 88 fe ad 82 c6 05 bf 40 98 01 01 e8 9b 95 95 ff <0f> 0b c3 cc cc cc cc 48 c7 c7 e0 fe ad 82 c6 05 a3 40 98 01 01 e8
> All code
> ========
> 0: 95 xchg %eax,%ebp
> 1: 95 xchg %eax,%ebp
> 2: ff 0f decl (%rdi)
> 4: 0b e9 or %ecx,%ebp
> 6: 4b rex.WXB
> 7: 45 90 rex.RB xchg %eax,%r8d
> 9: 00 80 3d d3 40 98 add %al,-0x67bf2cc3(%rax)
> f: 01 00 add %eax,(%rax)
> 11: 0f 85 5e ff ff ff jne 0xffffffffffffff75
> 17: 48 c7 c7 88 fe ad 82 mov $0xffffffff82adfe88,%rdi
> 1e: c6 05 bf 40 98 01 01 movb $0x1,0x19840bf(%rip) # 0x19840e4
> 25: e8 9b 95 95 ff call 0xffffffffff9595c5
> 2a:* 0f 0b ud2 <-- trapping instruction
> 2c: c3 ret
> 2d: cc int3
> 2e: cc int3
> 2f: cc int3
> 30: cc int3
> 31: 48 c7 c7 e0 fe ad 82 mov $0xffffffff82adfee0,%rdi
> 38: c6 05 a3 40 98 01 01 movb $0x1,0x19840a3(%rip) # 0x19840e2
> 3f: e8 .byte 0xe8
>
> Code starting with the faulting instruction
> ===========================================
> 0: 0f 0b ud2
> 2: c3 ret
> 3: cc int3
> 4: cc int3
> 5: cc int3
> 6: cc int3
> 7: 48 c7 c7 e0 fe ad 82 mov $0xffffffff82adfee0,%rdi
> e: c6 05 a3 40 98 01 01 movb $0x1,0x19840a3(%rip) # 0x19840b8
> 15: e8 .byte 0xe8
> [ 92.543676][ T1319] RSP: 0018:ffffc9000fcabca0 EFLAGS: 00010282
> [ 92.550187][ T1319] RAX: 0000000000000000 RBX: ffff888e3d2c8d68 RCX: 0000000000000000
> [ 92.558625][ T1319] RDX: ffff88984f36a3c0 RSI: 0000000000000001 RDI: ffff88984f35c200
> [ 92.567066][ T1319] RBP: ffff8881069c6368 R08: 00000000000008fd R09: 000000000000001d
> [ 92.575508][ T1319] R10: 5b5d393933353633 R11: 205d353131325420 R12: ffff888cd91ced20
> [ 92.583960][ T1319] R13: 0000000000081087 R14: ffff888ed98c2ba8 R15: ffff8881069c6000
> [ 92.592397][ T1319] FS: 0000000000000000(0000) GS:ffff8898cb53c000(0000) knlGS:0000000000000000
> [ 92.601843][ T1319] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 92.608920][ T1319] CR2: 0000000000000800 CR3: 0000002c7de24001 CR4: 00000000007726f0
> [ 92.617398][ T1319] PKRU: 55555554
> [ 92.621442][ T1319] Call Trace:
> [ 92.625216][ T1319] <TASK>
> [ 92.628645][ T1319] btrfs_get_delayed_node+0xda/0x1b0 btrfs
> [ 92.636027][ T1319] btrfs_get_or_create_delayed_node+0x12a/0x1b0 btrfs
> [ 92.644356][ T1319] btrfs_delayed_update_inode (fs/btrfs/delayed-inode.c:1957) btrfs
> [ 92.651387][ T1319] ? btrfs_update_root_times (fs/btrfs/root-tree.c:488) btrfs
> [ 92.658201][ T1319] btrfs_update_inode (fs/btrfs/inode.c:4174) btrfs
> [ 92.664431][ T1319] btrfs_finish_one_ordered (fs/btrfs/inode.c:4188 fs/btrfs/inode.c:3226) btrfs
> [ 92.671351][ T1319] btrfs_work_helper (fs/btrfs/async-thread.c:313) btrfs
> [ 92.677606][ T1319] process_one_work (arch/x86/include/asm/jump_label.h:36 include/trace/events/workqueue.h:110 kernel/workqueue.c:3241)
> [ 92.682972][ T1319] worker_thread (kernel/workqueue.c:3313 (discriminator 2) kernel/workqueue.c:3400 (discriminator 2))
> [ 92.688065][ T1319] ? __pfx_worker_thread (kernel/workqueue.c:3346)
> [ 92.693679][ T1319] kthread (kernel/kthread.c:463)
> [ 92.698145][ T1319] ? __pfx_kthread (kernel/kthread.c:412)
> [ 92.703205][ T1319] ret_from_fork (arch/x86/kernel/process.c:148)
> [ 92.708102][ T1319] ? __pfx_kthread (kernel/kthread.c:412)
> [ 92.713169][ T1319] ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
> [ 92.718420][ T1319] </TASK>
> [ 92.721904][ T1319] ---[ end trace 0000000000000000 ]---
> [ 92.772617][ T2117] [ perf record: Woken up 232 times to write data ]
> [ 92.772626][ T2117]
> [ 97.041836][ T2115] 2696 307116 30435 210930 28018 143529 49252
> [ 97.041848][ T2115]
> [ 107.042097][ T2115] 3311 309408 37927 214378 34672 141593 71871
> [ 107.042111][ T2115]
> [ 107.492140][ T2117] Warning:
> [ 107.492150][ T2117]
> [ 107.504083][ T2117] 174 out of order events recorded.
> [ 107.504089][ T2117]
> [ 107.572544][ T2117] [ perf record: Captured and wrote 680.421 MB /tmp/lkp/perf-sched.data (2685986 samples) ]
> [ 107.572552][ T2117]
> [ 116.735824][ C3] perf: interrupt took too long (2518 > 2500), lowering kernel.perf_event_max_sample_rate to 79000
> [ 116.747160][ C3] perf: interrupt took too long (3163 > 3147), lowering kernel.perf_event_max_sample_rate to 63000
> [ 116.760698][ T2117] Events enabled
> [ 116.760708][ T2117]
> [ 116.763935][ C3] perf: interrupt took too long (3955 > 3953), lowering kernel.perf_event_max_sample_rate to 50000
> [ 116.796549][ C67] perf: interrupt took too long (4953 > 4943), lowering kernel.perf_event_max_sample_rate to 40000
> [ 116.866088][ C131] perf: interrupt took too long (6210 > 6191), lowering kernel.perf_event_max_sample_rate to 32000
> [ 117.042049][ T2115] 3836 310809 30767 213835 28646 137339 48846
> [ 117.042057][ T2115]
> [ 117.739156][ C25] perf: interrupt took too long (7763 > 7762), lowering kernel.perf_event_max_sample_rate to 25000
> [ 119.838008][ T2117] [ perf record: Woken up 399 times to write data ]
> [ 119.838018][ T2117]
> [ 124.613970][ T2117] Warning:
> [ 124.613980][ T2117]
> [ 124.625324][ T2117] Processed 1601669 events and lost 6 chunks!
> [ 124.625332][ T2117]
> [ 124.635344][ T2117]
> [ 124.635349][ T2117]
> [ 124.642513][ T2117] Check IO/CPU overload!
> [ 124.642518][ T2117]
> [ 124.649994][ T2117]
> [ 124.649999][ T2117]
> [ 124.656077][ T2117] Warning:
> [ 124.656082][ T2117]
> [ 124.664342][ T2117] 35 out of order events recorded.
> [ 124.664347][ T2117]
> [ 124.678444][ T2117] [ perf record: Captured and wrote 252.317 MB /tmp/lkp/perf_c2c.data (1412807 samples) ]
> [ 124.678450][ T2117]
> [ 127.042332][ T2115] 4407 303071 35022 208647 31346 136630 47202
> [ 127.042344][ T2115]
> [ 137.042250][ T2115] 4943 299584 31810 208626 30129 128390 56528
> [ 137.042263][ T2115]
> [ 147.042441][ T2115] 5385 300009 27874 208644 24778 132677 46221
> [ 147.042453][ T2115]
> [ 157.042433][ T2115] 5910 307972 30431 216088 28665 137389 57696
> [ 157.042445][ T2115]
> [ 167.042628][ T2115] 6460 304663 35022 213949 31758 139786 62225
> [ 167.042640][ T2115]
> [ 177.042573][ T2115] 6967 307323 30606 213465 26983 141516 63168
> [ 177.042587][ T2115]
> [ 187.042733][ T2115] 7407 307075 26787 213546 24994 142923 41523
> [ 187.042745][ T2115]
> [ 197.042791][ T2115] 7927 308105 34190 214356 29643 140592 52914
> [ 197.042803][ T2115]
> [ 207.042918][ T2115] 8549 301948 38038 210474 34706 141120 67811
> [ 207.042931][ T2115]
> [ 217.042636][ T2115] 8955 297050 25135 208501 22518 135881 44260
> [ 217.042648][ T2115]
> [ 227.038865][ T2115] 9471 304296 32936 210610 29938 137844 62809
> [ 227.038870][ T2115]
> [ 237.038945][ T2115] 9964 305929 31628 213754 28012 141671 62429
> [ 237.038951][ T2115]
> [ 247.039008][ T2115] 10440 307726 30685 214830 28062 140111 62249
> [ 247.039015][ T2115]
> [ 257.039183][ T2115] 10802 292789 23345 205882 20689 138434 48453
> [ 257.039188][ T2115]
> [ 267.043497][ T2115] 11273 306881 30725 212403 27270 143693 60639
> [ 267.043508][ T2115]
> [ 277.043510][ T2115] 11797 302806 33279 211710 30071 142609 64344
> [ 277.043519][ T2115]
> [ 287.039432][ T2115] 12205 264441 24852 186434 24016 129256 56311
> [ 287.039437][ T2115]
> [ 297.043412][ T2115] 12673 310406 27331 217050 25960 146991 54571
> [ 297.043421][ T2115]
>
>
> The kernel config and materials to reproduce are available at:
> https://download.01.org/0day-ci/archive/20251126/202511262228.6dda231e-lkp@intel.com
>
>
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
Hello,
I believe I have identified the root cause of the warning.
However, I'm having some troubles running the reproducer as I
haven't setup lkp-tests yet. Could you test the patch below
against your reproducer to see if it fixes the issue?
---8<---
[PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
refcount before acquiring the root->delayed_nodes lock.
Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
moves refcount_set inside the critical section which means
there is no longer a memory barrier between setting the refcount and
setting btrfs_inode->delayed_node = node.
This allows btrfs_get_or_create_delayed_node to set
btrfs_inode->delayed_node before setting the refcount.
A different thread is then able to read and increase the refcount
of btrfs_inode->delayed_node leading to a refcounting bug and
a use-after-free warning.
The fix is to move refcount_set back to where it was to take
advantage of the implicit memory barrier provided by lock
acquisition.
Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
Signed-off-by: Leo Martins <loemra.dev@gmail.com>
---
fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 364814642a91..f61f10000e33 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
return ERR_PTR(-ENOMEM);
btrfs_init_delayed_node(node, root, ino);
+ /* Cached in the inode and can be accessed. */
+ refcount_set(&node->refs, 2);
+ btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
+ btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
+
/* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
- if (ret == -ENOMEM) {
- btrfs_delayed_node_ref_tracker_dir_exit(node);
- kmem_cache_free(delayed_node_cache, node);
- return ERR_PTR(-ENOMEM);
- }
+ if (ret == -ENOMEM)
+ goto cleanup;
+
xa_lock(&root->delayed_nodes);
ptr = xa_load(&root->delayed_nodes, ino);
if (ptr) {
/* Somebody inserted it, go back and read it. */
xa_unlock(&root->delayed_nodes);
- btrfs_delayed_node_ref_tracker_dir_exit(node);
- kmem_cache_free(delayed_node_cache, node);
- node = NULL;
- goto again;
+ goto cleanup;
}
ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
ASSERT(xa_err(ptr) != -EINVAL);
ASSERT(xa_err(ptr) != -ENOMEM);
ASSERT(ptr == NULL);
-
- /* Cached in the inode and can be accessed. */
- refcount_set(&node->refs, 2);
- btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
- btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
-
- btrfs_inode->delayed_node = node;
+ WRITE_ONCE(btrfs_inode->delayed_node, node);
xa_unlock(&root->delayed_nodes);
return node;
+cleanup:
+ btrfs_delayed_node_ref_tracker_free(node, tracker);
+ btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
+ btrfs_delayed_node_ref_tracker_dir_exit(node);
+ kmem_cache_free(delayed_node_cache, node);
+ if (ret)
+ return ERR_PTR(ret);
+ goto again;
}
/*
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 0:51 ` Leo Martins
@ 2025-12-02 8:40 ` Oliver Sang
2025-12-02 15:04 ` Filipe Manana
2025-12-02 17:18 ` Leo Martins
0 siblings, 2 replies; 9+ messages in thread
From: Oliver Sang @ 2025-12-02 8:40 UTC (permalink / raw)
To: Leo Martins
Cc: oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs, oliver.sang
hi, Leo Martins,
On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
[...]
>
> Hello,
>
> I believe I have identified the root cause of the warning.
> However, I'm having some troubles running the reproducer as I
> haven't setup lkp-tests yet. Could you test the patch below
> against your reproducer to see if it fixes the issue?
we confirmed your patch fixed the issues we reported in origial report. thanks!
Tested-by: kernel test robot <oliver.sang@intel.com>
>
> ---8<---
>
> [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
>
> Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> refcount before acquiring the root->delayed_nodes lock.
> Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> moves refcount_set inside the critical section which means
> there is no longer a memory barrier between setting the refcount and
> setting btrfs_inode->delayed_node = node.
>
> This allows btrfs_get_or_create_delayed_node to set
> btrfs_inode->delayed_node before setting the refcount.
> A different thread is then able to read and increase the refcount
> of btrfs_inode->delayed_node leading to a refcounting bug and
> a use-after-free warning.
>
> The fix is to move refcount_set back to where it was to take
> advantage of the implicit memory barrier provided by lock
> acquisition.
>
> Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> Reported-by: kernel test robot <oliver.sang@intel.com>
> Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> ---
> fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> 1 file changed, 18 insertions(+), 16 deletions(-)
>
> diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> index 364814642a91..f61f10000e33 100644
> --- a/fs/btrfs/delayed-inode.c
> +++ b/fs/btrfs/delayed-inode.c
> @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> return ERR_PTR(-ENOMEM);
> btrfs_init_delayed_node(node, root, ino);
>
> + /* Cached in the inode and can be accessed. */
> + refcount_set(&node->refs, 2);
> + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> +
> /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> - if (ret == -ENOMEM) {
> - btrfs_delayed_node_ref_tracker_dir_exit(node);
> - kmem_cache_free(delayed_node_cache, node);
> - return ERR_PTR(-ENOMEM);
> - }
> + if (ret == -ENOMEM)
> + goto cleanup;
> +
> xa_lock(&root->delayed_nodes);
> ptr = xa_load(&root->delayed_nodes, ino);
> if (ptr) {
> /* Somebody inserted it, go back and read it. */
> xa_unlock(&root->delayed_nodes);
> - btrfs_delayed_node_ref_tracker_dir_exit(node);
> - kmem_cache_free(delayed_node_cache, node);
> - node = NULL;
> - goto again;
> + goto cleanup;
> }
> ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> ASSERT(xa_err(ptr) != -EINVAL);
> ASSERT(xa_err(ptr) != -ENOMEM);
> ASSERT(ptr == NULL);
> -
> - /* Cached in the inode and can be accessed. */
> - refcount_set(&node->refs, 2);
> - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> -
> - btrfs_inode->delayed_node = node;
> + WRITE_ONCE(btrfs_inode->delayed_node, node);
> xa_unlock(&root->delayed_nodes);
>
> return node;
> +cleanup:
> + btrfs_delayed_node_ref_tracker_free(node, tracker);
> + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> + btrfs_delayed_node_ref_tracker_dir_exit(node);
> + kmem_cache_free(delayed_node_cache, node);
> + if (ret)
> + return ERR_PTR(ret);
> + goto again;
> }
>
> /*
> --
> 2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 8:40 ` Oliver Sang
@ 2025-12-02 15:04 ` Filipe Manana
2025-12-02 17:17 ` Leo Martins
2025-12-02 17:18 ` Leo Martins
1 sibling, 1 reply; 9+ messages in thread
From: Filipe Manana @ 2025-12-02 15:04 UTC (permalink / raw)
To: Oliver Sang
Cc: Leo Martins, oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, Dec 2, 2025 at 8:40 AM Oliver Sang <oliver.sang@intel.com> wrote:
>
> hi, Leo Martins,
>
> On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
>
> [...]
>
> >
> > Hello,
> >
> > I believe I have identified the root cause of the warning.
> > However, I'm having some troubles running the reproducer as I
> > haven't setup lkp-tests yet. Could you test the patch below
> > against your reproducer to see if it fixes the issue?
>
> we confirmed your patch fixed the issues we reported in origial report. thanks!
>
> Tested-by: kernel test robot <oliver.sang@intel.com>
>
> >
> > ---8<---
> >
> > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> >
> > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > refcount before acquiring the root->delayed_nodes lock.
> > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > moves refcount_set inside the critical section which means
> > there is no longer a memory barrier between setting the refcount and
> > setting btrfs_inode->delayed_node = node.
> >
> > This allows btrfs_get_or_create_delayed_node to set
> > btrfs_inode->delayed_node before setting the refcount.
> > A different thread is then able to read and increase the refcount
> > of btrfs_inode->delayed_node leading to a refcounting bug and
> > a use-after-free warning.
> >
> > The fix is to move refcount_set back to where it was to take
> > advantage of the implicit memory barrier provided by lock
> > acquisition.
> >
> > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > Reported-by: kernel test robot <oliver.sang@intel.com>
> > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > ---
> > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > 1 file changed, 18 insertions(+), 16 deletions(-)
> >
> > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > index 364814642a91..f61f10000e33 100644
> > --- a/fs/btrfs/delayed-inode.c
> > +++ b/fs/btrfs/delayed-inode.c
> > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > return ERR_PTR(-ENOMEM);
> > btrfs_init_delayed_node(node, root, ino);
> >
> > + /* Cached in the inode and can be accessed. */
> > + refcount_set(&node->refs, 2);
> > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > +
> > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > - if (ret == -ENOMEM) {
> > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > - kmem_cache_free(delayed_node_cache, node);
> > - return ERR_PTR(-ENOMEM);
> > - }
> > + if (ret == -ENOMEM)
> > + goto cleanup;
> > +
> > xa_lock(&root->delayed_nodes);
> > ptr = xa_load(&root->delayed_nodes, ino);
> > if (ptr) {
> > /* Somebody inserted it, go back and read it. */
> > xa_unlock(&root->delayed_nodes);
> > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > - kmem_cache_free(delayed_node_cache, node);
> > - node = NULL;
> > - goto again;
> > + goto cleanup;
> > }
> > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > ASSERT(xa_err(ptr) != -EINVAL);
> > ASSERT(xa_err(ptr) != -ENOMEM);
> > ASSERT(ptr == NULL);
> > -
> > - /* Cached in the inode and can be accessed. */
> > - refcount_set(&node->refs, 2);
> > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > -
> > - btrfs_inode->delayed_node = node;
> > + WRITE_ONCE(btrfs_inode->delayed_node, node);
Why the WRITE_ONCE() change?
Can you explain in the changelog why it's being introduced?
This seems unrelated and it was not there before the commit mentioned
in the Fixes tag.
Thanks.
> > xa_unlock(&root->delayed_nodes);
> >
> > return node;
> > +cleanup:
> > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > + kmem_cache_free(delayed_node_cache, node);
> > + if (ret)
> > + return ERR_PTR(ret);
> > + goto again;
> > }
> >
> > /*
> > --
> > 2.47.3
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 15:04 ` Filipe Manana
@ 2025-12-02 17:17 ` Leo Martins
2025-12-02 19:19 ` Filipe Manana
0 siblings, 1 reply; 9+ messages in thread
From: Leo Martins @ 2025-12-02 17:17 UTC (permalink / raw)
To: Filipe Manana
Cc: Oliver Sang, oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, 2 Dec 2025 15:04:51 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
> On Tue, Dec 2, 2025 at 8:40 AM Oliver Sang <oliver.sang@intel.com> wrote:
> >
> > hi, Leo Martins,
> >
> > On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
> >
> > [...]
> >
> > >
> > > Hello,
> > >
> > > I believe I have identified the root cause of the warning.
> > > However, I'm having some troubles running the reproducer as I
> > > haven't setup lkp-tests yet. Could you test the patch below
> > > against your reproducer to see if it fixes the issue?
> >
> > we confirmed your patch fixed the issues we reported in origial report. thanks!
> >
> > Tested-by: kernel test robot <oliver.sang@intel.com>
> >
> > >
> > > ---8<---
> > >
> > > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> > >
> > > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > > refcount before acquiring the root->delayed_nodes lock.
> > > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > moves refcount_set inside the critical section which means
> > > there is no longer a memory barrier between setting the refcount and
> > > setting btrfs_inode->delayed_node = node.
> > >
> > > This allows btrfs_get_or_create_delayed_node to set
> > > btrfs_inode->delayed_node before setting the refcount.
> > > A different thread is then able to read and increase the refcount
> > > of btrfs_inode->delayed_node leading to a refcounting bug and
> > > a use-after-free warning.
> > >
> > > The fix is to move refcount_set back to where it was to take
> > > advantage of the implicit memory barrier provided by lock
> > > acquisition.
> > >
> > > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > Reported-by: kernel test robot <oliver.sang@intel.com>
> > > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > > ---
> > > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > > 1 file changed, 18 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > > index 364814642a91..f61f10000e33 100644
> > > --- a/fs/btrfs/delayed-inode.c
> > > +++ b/fs/btrfs/delayed-inode.c
> > > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > > return ERR_PTR(-ENOMEM);
> > > btrfs_init_delayed_node(node, root, ino);
> > >
> > > + /* Cached in the inode and can be accessed. */
> > > + refcount_set(&node->refs, 2);
> > > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > +
> > > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > > - if (ret == -ENOMEM) {
> > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > - kmem_cache_free(delayed_node_cache, node);
> > > - return ERR_PTR(-ENOMEM);
> > > - }
> > > + if (ret == -ENOMEM)
> > > + goto cleanup;
> > > +
> > > xa_lock(&root->delayed_nodes);
> > > ptr = xa_load(&root->delayed_nodes, ino);
> > > if (ptr) {
> > > /* Somebody inserted it, go back and read it. */
> > > xa_unlock(&root->delayed_nodes);
> > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > - kmem_cache_free(delayed_node_cache, node);
> > > - node = NULL;
> > > - goto again;
> > > + goto cleanup;
> > > }
> > > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > > ASSERT(xa_err(ptr) != -EINVAL);
> > > ASSERT(xa_err(ptr) != -ENOMEM);
> > > ASSERT(ptr == NULL);
> > > -
> > > - /* Cached in the inode and can be accessed. */
> > > - refcount_set(&node->refs, 2);
> > > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > -
> > > - btrfs_inode->delayed_node = node;
> > > + WRITE_ONCE(btrfs_inode->delayed_node, node);
>
> Why the WRITE_ONCE() change?
Since there are lockless readers of btrfs_inode->delayed_node all writers
should be marked with WRITE_ONCE to force the compiler to store atomically.
>
> Can you explain in the changelog why it's being introduced?
> This seems unrelated and it was not there before the commit mentioned
> in the Fixes tag.
I'll send out a v2 without the WRITE_ONCE since it is not directly related
to this bug and send out a separate patch updating writes to use WRITE_ONCE.
Thanks.
>
> Thanks.
>
> > > xa_unlock(&root->delayed_nodes);
> > >
> > > return node;
> > > +cleanup:
> > > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > + kmem_cache_free(delayed_node_cache, node);
> > > + if (ret)
> > > + return ERR_PTR(ret);
> > > + goto again;
> > > }
> > >
> > > /*
> > > --
> > > 2.47.3
> >
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 8:40 ` Oliver Sang
2025-12-02 15:04 ` Filipe Manana
@ 2025-12-02 17:18 ` Leo Martins
1 sibling, 0 replies; 9+ messages in thread
From: Leo Martins @ 2025-12-02 17:18 UTC (permalink / raw)
To: Oliver Sang; +Cc: oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, 2 Dec 2025 16:40:06 +0800 Oliver Sang <oliver.sang@intel.com> wrote:
> hi, Leo Martins,
>
> On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
>
> [...]
>
> >
> > Hello,
> >
> > I believe I have identified the root cause of the warning.
> > However, I'm having some troubles running the reproducer as I
> > haven't setup lkp-tests yet. Could you test the patch below
> > against your reproducer to see if it fixes the issue?
>
> we confirmed your patch fixed the issues we reported in origial report. thanks!
>
> Tested-by: kernel test robot <oliver.sang@intel.com>
Thank you, for the help!
>
> >
> > ---8<---
> >
> > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> >
> > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > refcount before acquiring the root->delayed_nodes lock.
> > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > moves refcount_set inside the critical section which means
> > there is no longer a memory barrier between setting the refcount and
> > setting btrfs_inode->delayed_node = node.
> >
> > This allows btrfs_get_or_create_delayed_node to set
> > btrfs_inode->delayed_node before setting the refcount.
> > A different thread is then able to read and increase the refcount
> > of btrfs_inode->delayed_node leading to a refcounting bug and
> > a use-after-free warning.
> >
> > The fix is to move refcount_set back to where it was to take
> > advantage of the implicit memory barrier provided by lock
> > acquisition.
> >
> > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > Reported-by: kernel test robot <oliver.sang@intel.com>
> > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > ---
> > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > 1 file changed, 18 insertions(+), 16 deletions(-)
> >
> > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > index 364814642a91..f61f10000e33 100644
> > --- a/fs/btrfs/delayed-inode.c
> > +++ b/fs/btrfs/delayed-inode.c
> > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > return ERR_PTR(-ENOMEM);
> > btrfs_init_delayed_node(node, root, ino);
> >
> > + /* Cached in the inode and can be accessed. */
> > + refcount_set(&node->refs, 2);
> > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > +
> > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > - if (ret == -ENOMEM) {
> > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > - kmem_cache_free(delayed_node_cache, node);
> > - return ERR_PTR(-ENOMEM);
> > - }
> > + if (ret == -ENOMEM)
> > + goto cleanup;
> > +
> > xa_lock(&root->delayed_nodes);
> > ptr = xa_load(&root->delayed_nodes, ino);
> > if (ptr) {
> > /* Somebody inserted it, go back and read it. */
> > xa_unlock(&root->delayed_nodes);
> > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > - kmem_cache_free(delayed_node_cache, node);
> > - node = NULL;
> > - goto again;
> > + goto cleanup;
> > }
> > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > ASSERT(xa_err(ptr) != -EINVAL);
> > ASSERT(xa_err(ptr) != -ENOMEM);
> > ASSERT(ptr == NULL);
> > -
> > - /* Cached in the inode and can be accessed. */
> > - refcount_set(&node->refs, 2);
> > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > -
> > - btrfs_inode->delayed_node = node;
> > + WRITE_ONCE(btrfs_inode->delayed_node, node);
> > xa_unlock(&root->delayed_nodes);
> >
> > return node;
> > +cleanup:
> > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > + kmem_cache_free(delayed_node_cache, node);
> > + if (ret)
> > + return ERR_PTR(ret);
> > + goto again;
> > }
> >
> > /*
> > --
> > 2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 17:17 ` Leo Martins
@ 2025-12-02 19:19 ` Filipe Manana
2025-12-02 21:03 ` Leo Martins
0 siblings, 1 reply; 9+ messages in thread
From: Filipe Manana @ 2025-12-02 19:19 UTC (permalink / raw)
To: Leo Martins
Cc: Oliver Sang, oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, Dec 2, 2025 at 5:17 PM Leo Martins <loemra.dev@gmail.com> wrote:
>
> On Tue, 2 Dec 2025 15:04:51 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
>
> > On Tue, Dec 2, 2025 at 8:40 AM Oliver Sang <oliver.sang@intel.com> wrote:
> > >
> > > hi, Leo Martins,
> > >
> > > On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
> > >
> > > [...]
> > >
> > > >
> > > > Hello,
> > > >
> > > > I believe I have identified the root cause of the warning.
> > > > However, I'm having some troubles running the reproducer as I
> > > > haven't setup lkp-tests yet. Could you test the patch below
> > > > against your reproducer to see if it fixes the issue?
> > >
> > > we confirmed your patch fixed the issues we reported in origial report. thanks!
> > >
> > > Tested-by: kernel test robot <oliver.sang@intel.com>
> > >
> > > >
> > > > ---8<---
> > > >
> > > > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> > > >
> > > > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > > > refcount before acquiring the root->delayed_nodes lock.
> > > > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > moves refcount_set inside the critical section which means
> > > > there is no longer a memory barrier between setting the refcount and
> > > > setting btrfs_inode->delayed_node = node.
> > > >
> > > > This allows btrfs_get_or_create_delayed_node to set
> > > > btrfs_inode->delayed_node before setting the refcount.
> > > > A different thread is then able to read and increase the refcount
> > > > of btrfs_inode->delayed_node leading to a refcounting bug and
> > > > a use-after-free warning.
> > > >
> > > > The fix is to move refcount_set back to where it was to take
> > > > advantage of the implicit memory barrier provided by lock
> > > > acquisition.
> > > >
> > > > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > Reported-by: kernel test robot <oliver.sang@intel.com>
> > > > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > > > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > > > ---
> > > > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > > > 1 file changed, 18 insertions(+), 16 deletions(-)
> > > >
> > > > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > > > index 364814642a91..f61f10000e33 100644
> > > > --- a/fs/btrfs/delayed-inode.c
> > > > +++ b/fs/btrfs/delayed-inode.c
> > > > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > > > return ERR_PTR(-ENOMEM);
> > > > btrfs_init_delayed_node(node, root, ino);
> > > >
> > > > + /* Cached in the inode and can be accessed. */
> > > > + refcount_set(&node->refs, 2);
> > > > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > +
> > > > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > > > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > > > - if (ret == -ENOMEM) {
> > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > - kmem_cache_free(delayed_node_cache, node);
> > > > - return ERR_PTR(-ENOMEM);
> > > > - }
> > > > + if (ret == -ENOMEM)
> > > > + goto cleanup;
> > > > +
> > > > xa_lock(&root->delayed_nodes);
> > > > ptr = xa_load(&root->delayed_nodes, ino);
> > > > if (ptr) {
> > > > /* Somebody inserted it, go back and read it. */
> > > > xa_unlock(&root->delayed_nodes);
> > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > - kmem_cache_free(delayed_node_cache, node);
> > > > - node = NULL;
> > > > - goto again;
> > > > + goto cleanup;
> > > > }
> > > > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > > > ASSERT(xa_err(ptr) != -EINVAL);
> > > > ASSERT(xa_err(ptr) != -ENOMEM);
> > > > ASSERT(ptr == NULL);
> > > > -
> > > > - /* Cached in the inode and can be accessed. */
> > > > - refcount_set(&node->refs, 2);
> > > > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > -
> > > > - btrfs_inode->delayed_node = node;
> > > > + WRITE_ONCE(btrfs_inode->delayed_node, node);
> >
> > Why the WRITE_ONCE() change?
>
> Since there are lockless readers of btrfs_inode->delayed_node all writers
> should be marked with WRITE_ONCE to force the compiler to store atomically.
If by atomically you mean to avoid store/load tearing, then using the
_ONCE() macros won't do anything because we are dealing with pointers.
This has been discussed in the past, see:
https://lore.kernel.org/linux-btrfs/cover.1715951291.git.fdmanana@suse.com/
>
> >
> > Can you explain in the changelog why it's being introduced?
> > This seems unrelated and it was not there before the commit mentioned
> > in the Fixes tag.
>
> I'll send out a v2 without the WRITE_ONCE since it is not directly related
> to this bug and send out a separate patch updating writes to use WRITE_ONCE.
>
> Thanks.
>
> >
> > Thanks.
> >
> > > > xa_unlock(&root->delayed_nodes);
> > > >
> > > > return node;
> > > > +cleanup:
> > > > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > > > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > > > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > + kmem_cache_free(delayed_node_cache, node);
> > > > + if (ret)
> > > > + return ERR_PTR(ret);
> > > > + goto again;
> > > > }
> > > >
> > > > /*
> > > > --
> > > > 2.47.3
> > >
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 19:19 ` Filipe Manana
@ 2025-12-02 21:03 ` Leo Martins
2025-12-03 10:45 ` Filipe Manana
0 siblings, 1 reply; 9+ messages in thread
From: Leo Martins @ 2025-12-02 21:03 UTC (permalink / raw)
To: Filipe Manana
Cc: Oliver Sang, oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, 2 Dec 2025 19:19:05 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
> On Tue, Dec 2, 2025 at 5:17 PM Leo Martins <loemra.dev@gmail.com> wrote:
> >
> > On Tue, 2 Dec 2025 15:04:51 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
> >
> > > On Tue, Dec 2, 2025 at 8:40 AM Oliver Sang <oliver.sang@intel.com> wrote:
> > > >
> > > > hi, Leo Martins,
> > > >
> > > > On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
> > > >
> > > > [...]
> > > >
> > > > >
> > > > > Hello,
> > > > >
> > > > > I believe I have identified the root cause of the warning.
> > > > > However, I'm having some troubles running the reproducer as I
> > > > > haven't setup lkp-tests yet. Could you test the patch below
> > > > > against your reproducer to see if it fixes the issue?
> > > >
> > > > we confirmed your patch fixed the issues we reported in origial report. thanks!
> > > >
> > > > Tested-by: kernel test robot <oliver.sang@intel.com>
> > > >
> > > > >
> > > > > ---8<---
> > > > >
> > > > > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> > > > >
> > > > > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > > > > refcount before acquiring the root->delayed_nodes lock.
> > > > > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > > moves refcount_set inside the critical section which means
> > > > > there is no longer a memory barrier between setting the refcount and
> > > > > setting btrfs_inode->delayed_node = node.
> > > > >
> > > > > This allows btrfs_get_or_create_delayed_node to set
> > > > > btrfs_inode->delayed_node before setting the refcount.
> > > > > A different thread is then able to read and increase the refcount
> > > > > of btrfs_inode->delayed_node leading to a refcounting bug and
> > > > > a use-after-free warning.
> > > > >
> > > > > The fix is to move refcount_set back to where it was to take
> > > > > advantage of the implicit memory barrier provided by lock
> > > > > acquisition.
> > > > >
> > > > > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > > Reported-by: kernel test robot <oliver.sang@intel.com>
> > > > > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > > > > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > > > > ---
> > > > > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > > > > 1 file changed, 18 insertions(+), 16 deletions(-)
> > > > >
> > > > > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > > > > index 364814642a91..f61f10000e33 100644
> > > > > --- a/fs/btrfs/delayed-inode.c
> > > > > +++ b/fs/btrfs/delayed-inode.c
> > > > > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > > > > return ERR_PTR(-ENOMEM);
> > > > > btrfs_init_delayed_node(node, root, ino);
> > > > >
> > > > > + /* Cached in the inode and can be accessed. */
> > > > > + refcount_set(&node->refs, 2);
> > > > > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > > +
> > > > > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > > > > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > > > > - if (ret == -ENOMEM) {
> > > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > - kmem_cache_free(delayed_node_cache, node);
> > > > > - return ERR_PTR(-ENOMEM);
> > > > > - }
> > > > > + if (ret == -ENOMEM)
> > > > > + goto cleanup;
> > > > > +
> > > > > xa_lock(&root->delayed_nodes);
> > > > > ptr = xa_load(&root->delayed_nodes, ino);
> > > > > if (ptr) {
> > > > > /* Somebody inserted it, go back and read it. */
> > > > > xa_unlock(&root->delayed_nodes);
> > > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > - kmem_cache_free(delayed_node_cache, node);
> > > > > - node = NULL;
> > > > > - goto again;
> > > > > + goto cleanup;
> > > > > }
> > > > > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > > > > ASSERT(xa_err(ptr) != -EINVAL);
> > > > > ASSERT(xa_err(ptr) != -ENOMEM);
> > > > > ASSERT(ptr == NULL);
> > > > > -
> > > > > - /* Cached in the inode and can be accessed. */
> > > > > - refcount_set(&node->refs, 2);
> > > > > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > > -
> > > > > - btrfs_inode->delayed_node = node;
> > > > > + WRITE_ONCE(btrfs_inode->delayed_node, node);
> > >
> > > Why the WRITE_ONCE() change?
> >
> > Since there are lockless readers of btrfs_inode->delayed_node all writers
> > should be marked with WRITE_ONCE to force the compiler to store atomically.
>
> If by atomically you mean to avoid store/load tearing, then using the
> _ONCE() macros won't do anything because we are dealing with pointers.
> This has been discussed in the past, see:
>
> https://lore.kernel.org/linux-btrfs/cover.1715951291.git.fdmanana@suse.com/
That is what I meant. Missed that discussion, thanks for the link.
I do still see some value in using WRITE_ONCE which is for the human
reader to realize that there are lockless readers, but that's pretty
minor.
>
> >
> > >
> > > Can you explain in the changelog why it's being introduced?
> > > This seems unrelated and it was not there before the commit mentioned
> > > in the Fixes tag.
> >
> > I'll send out a v2 without the WRITE_ONCE since it is not directly related
> > to this bug and send out a separate patch updating writes to use WRITE_ONCE.
> >
> > Thanks.
> >
> > >
> > > Thanks.
> > >
> > > > > xa_unlock(&root->delayed_nodes);
> > > > >
> > > > > return node;
> > > > > +cleanup:
> > > > > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > > > > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > > > > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > + kmem_cache_free(delayed_node_cache, node);
> > > > > + if (ret)
> > > > > + return ERR_PTR(ret);
> > > > > + goto again;
> > > > > }
> > > > >
> > > > > /*
> > > > > --
> > > > > 2.47.3
> > > >
> >
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free
2025-12-02 21:03 ` Leo Martins
@ 2025-12-03 10:45 ` Filipe Manana
0 siblings, 0 replies; 9+ messages in thread
From: Filipe Manana @ 2025-12-03 10:45 UTC (permalink / raw)
To: Leo Martins
Cc: Oliver Sang, oe-lkp, lkp, linux-kernel, David Sterba, linux-btrfs
On Tue, Dec 2, 2025 at 9:03 PM Leo Martins <loemra.dev@gmail.com> wrote:
>
> On Tue, 2 Dec 2025 19:19:05 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
>
> > On Tue, Dec 2, 2025 at 5:17 PM Leo Martins <loemra.dev@gmail.com> wrote:
> > >
> > > On Tue, 2 Dec 2025 15:04:51 +0000 Filipe Manana <fdmanana@kernel.org> wrote:
> > >
> > > > On Tue, Dec 2, 2025 at 8:40 AM Oliver Sang <oliver.sang@intel.com> wrote:
> > > > >
> > > > > hi, Leo Martins,
> > > > >
> > > > > On Mon, Dec 01, 2025 at 04:51:41PM -0800, Leo Martins wrote:
> > > > >
> > > > > [...]
> > > > >
> > > > > >
> > > > > > Hello,
> > > > > >
> > > > > > I believe I have identified the root cause of the warning.
> > > > > > However, I'm having some troubles running the reproducer as I
> > > > > > haven't setup lkp-tests yet. Could you test the patch below
> > > > > > against your reproducer to see if it fixes the issue?
> > > > >
> > > > > we confirmed your patch fixed the issues we reported in origial report. thanks!
> > > > >
> > > > > Tested-by: kernel test robot <oliver.sang@intel.com>
> > > > >
> > > > > >
> > > > > > ---8<---
> > > > > >
> > > > > > [PATCH] btrfs: fix use-after-free in btrfs_get_or_create_delayed_node
> > > > > >
> > > > > > Previously, btrfs_get_or_create_delayed_node sets the delayed_node's
> > > > > > refcount before acquiring the root->delayed_nodes lock.
> > > > > > Commit e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > > > moves refcount_set inside the critical section which means
> > > > > > there is no longer a memory barrier between setting the refcount and
> > > > > > setting btrfs_inode->delayed_node = node.
> > > > > >
> > > > > > This allows btrfs_get_or_create_delayed_node to set
> > > > > > btrfs_inode->delayed_node before setting the refcount.
> > > > > > A different thread is then able to read and increase the refcount
> > > > > > of btrfs_inode->delayed_node leading to a refcounting bug and
> > > > > > a use-after-free warning.
> > > > > >
> > > > > > The fix is to move refcount_set back to where it was to take
> > > > > > advantage of the implicit memory barrier provided by lock
> > > > > > acquisition.
> > > > > >
> > > > > > Fixes: e8513c012de7 ("btrfs: implement ref_tracker for delayed_nodes")
> > > > > > Reported-by: kernel test robot <oliver.sang@intel.com>
> > > > > > Closes: https://lore.kernel.org/oe-lkp/202511262228.6dda231e-lkp@intel.com
> > > > > > Signed-off-by: Leo Martins <loemra.dev@gmail.com>
> > > > > > ---
> > > > > > fs/btrfs/delayed-inode.c | 34 ++++++++++++++++++----------------
> > > > > > 1 file changed, 18 insertions(+), 16 deletions(-)
> > > > > >
> > > > > > diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
> > > > > > index 364814642a91..f61f10000e33 100644
> > > > > > --- a/fs/btrfs/delayed-inode.c
> > > > > > +++ b/fs/btrfs/delayed-inode.c
> > > > > > @@ -152,37 +152,39 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
> > > > > > return ERR_PTR(-ENOMEM);
> > > > > > btrfs_init_delayed_node(node, root, ino);
> > > > > >
> > > > > > + /* Cached in the inode and can be accessed. */
> > > > > > + refcount_set(&node->refs, 2);
> > > > > > + btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > > > + btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > > > +
> > > > > > /* Allocate and reserve the slot, from now it can return a NULL from xa_load(). */
> > > > > > ret = xa_reserve(&root->delayed_nodes, ino, GFP_NOFS);
> > > > > > - if (ret == -ENOMEM) {
> > > > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > > - kmem_cache_free(delayed_node_cache, node);
> > > > > > - return ERR_PTR(-ENOMEM);
> > > > > > - }
> > > > > > + if (ret == -ENOMEM)
> > > > > > + goto cleanup;
> > > > > > +
> > > > > > xa_lock(&root->delayed_nodes);
> > > > > > ptr = xa_load(&root->delayed_nodes, ino);
> > > > > > if (ptr) {
> > > > > > /* Somebody inserted it, go back and read it. */
> > > > > > xa_unlock(&root->delayed_nodes);
> > > > > > - btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > > - kmem_cache_free(delayed_node_cache, node);
> > > > > > - node = NULL;
> > > > > > - goto again;
> > > > > > + goto cleanup;
> > > > > > }
> > > > > > ptr = __xa_store(&root->delayed_nodes, ino, node, GFP_ATOMIC);
> > > > > > ASSERT(xa_err(ptr) != -EINVAL);
> > > > > > ASSERT(xa_err(ptr) != -ENOMEM);
> > > > > > ASSERT(ptr == NULL);
> > > > > > -
> > > > > > - /* Cached in the inode and can be accessed. */
> > > > > > - refcount_set(&node->refs, 2);
> > > > > > - btrfs_delayed_node_ref_tracker_alloc(node, tracker, GFP_ATOMIC);
> > > > > > - btrfs_delayed_node_ref_tracker_alloc(node, &node->inode_cache_tracker, GFP_ATOMIC);
> > > > > > -
> > > > > > - btrfs_inode->delayed_node = node;
> > > > > > + WRITE_ONCE(btrfs_inode->delayed_node, node);
> > > >
> > > > Why the WRITE_ONCE() change?
> > >
> > > Since there are lockless readers of btrfs_inode->delayed_node all writers
> > > should be marked with WRITE_ONCE to force the compiler to store atomically.
> >
> > If by atomically you mean to avoid store/load tearing, then using the
> > _ONCE() macros won't do anything because we are dealing with pointers.
> > This has been discussed in the past, see:
> >
> > https://lore.kernel.org/linux-btrfs/cover.1715951291.git.fdmanana@suse.com/
>
> That is what I meant. Missed that discussion, thanks for the link.
> I do still see some value in using WRITE_ONCE which is for the human
> reader to realize that there are lockless readers, but that's pretty
> minor.
No and that's mentioned in the thread: using _ONCE() when it doesn't
offer any protection but to signal someone reading the source code
that it can be accessed in a lockless way is only confusing people and
influencing people to repeat this pattern.
To make it clear that it's accessed in a lockless way, just make the
reader side use data_race() if it's a safe race or smp_load_acquire()
otherwise, with proper comments right above the read access. These
also make KCSAN and other tools not report possible races.
> >
> > >
> > > >
> > > > Can you explain in the changelog why it's being introduced?
> > > > This seems unrelated and it was not there before the commit mentioned
> > > > in the Fixes tag.
> > >
> > > I'll send out a v2 without the WRITE_ONCE since it is not directly related
> > > to this bug and send out a separate patch updating writes to use WRITE_ONCE.
> > >
> > > Thanks.
> > >
> > > >
> > > > Thanks.
> > > >
> > > > > > xa_unlock(&root->delayed_nodes);
> > > > > >
> > > > > > return node;
> > > > > > +cleanup:
> > > > > > + btrfs_delayed_node_ref_tracker_free(node, tracker);
> > > > > > + btrfs_delayed_node_ref_tracker_free(node, &node->inode_cache_tracker);
> > > > > > + btrfs_delayed_node_ref_tracker_dir_exit(node);
> > > > > > + kmem_cache_free(delayed_node_cache, node);
> > > > > > + if (ret)
> > > > > > + return ERR_PTR(ret);
> > > > > > + goto again;
> > > > > > }
> > > > > >
> > > > > > /*
> > > > > > --
> > > > > > 2.47.3
> > > > >
> > >
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-12-03 10:45 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-26 14:23 [linus:master] [btrfs] e8513c012d: addition_on#;use-after-free kernel test robot
2025-12-02 0:51 ` Leo Martins
2025-12-02 8:40 ` Oliver Sang
2025-12-02 15:04 ` Filipe Manana
2025-12-02 17:17 ` Leo Martins
2025-12-02 19:19 ` Filipe Manana
2025-12-02 21:03 ` Leo Martins
2025-12-03 10:45 ` Filipe Manana
2025-12-02 17:18 ` Leo Martins
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox