]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: tracepoints: fix sleep while in atomic context in btrfs_sync_file()
authorFilipe Manana <fdmanana@suse.com>
Tue, 28 Apr 2026 15:58:56 +0000 (16:58 +0100)
committerDavid Sterba <dsterba@suse.com>
Thu, 7 May 2026 22:31:37 +0000 (00:31 +0200)
The trace event btrfs_sync_file() is called in an atomic context (all trace
events are) and its call to dput(), which is needed due to the call to
dget_parent(), can sleep, triggering a kernel splat.

This can be reproduced by enabling the trace event and running btrfs/056
from fstests for example. The splat shown in dmesg is the following:

  [53.919] BUG: sleeping function called from invalid context at fs/dcache.c:970
  [53.947] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 32773, name: xfs_io
  [53.988] preempt_count: 2, expected: 0
  [53.967] RCU nest depth: 0, expected: 0
  [53.943] Preemption disabled at:
  [53.944] [<0000000000000000>] 0x0
  [54.078] CPU: 0 UID: 0 PID: 32773 Comm: xfs_io Tainted: G        W           7.1.0-rc1-btrfs-next-232+ #1 PREEMPT(full)
  [54.070] Tainted: [W]=WARN
  [54.071] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014
  [54.072] Call Trace:
  [54.074]  <TASK>
  [54.076]  dump_stack_lvl+0x56/0x80
  [54.079]  __might_resched.cold+0xd6/0x10f
  [54.072]  dput.part.0+0x24/0x110
  [54.078]  trace_event_raw_event_btrfs_sync_file+0x75/0x140 [btrfs]
  [54.089]  btrfs_sync_file+0x1ed/0x530 [btrfs]
  [54.087]  ? __handle_mm_fault+0x8ae/0xed0
  [54.089]  btrfs_do_write_iter+0x172/0x210 [btrfs]
  [54.091]  vfs_write+0x21f/0x450
  [54.094]  __x64_sys_pwrite64+0x8d/0xc0
  [54.096]  ? do_user_addr_fault+0x20c/0x670
  [54.099]  do_syscall_64+0x60/0xf20
  [54.092]  ? clear_bhb_loop+0x60/0xb0
  [54.094]  entry_SYSCALL_64_after_hwframe+0x76/0x7e

So stop using dget_parent() and dput() and access the parent dentry
directly as dentry->d_parent. This is also what ext4 is doing in
its equivalent trace event ext4_sync_file_enter().

Fixes: a85b46db143f ("btrfs: tracepoints: get correct superblock from dentry in event btrfs_sync_file()")
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
include/trace/events/btrfs.h

index 8ad7a2d76c1d57a92f225f0fae437b977decbc05..ec1df8b94517c5dcaa5eb6448f20e7c03c36f766 100644 (file)
@@ -771,10 +771,8 @@ TRACE_EVENT(btrfs_sync_file,
        TP_fast_assign(
                struct dentry *dentry = file_dentry(file);
                struct inode *inode = file_inode(file);
-               struct dentry *parent = dget_parent(dentry);
-               struct inode *parent_inode = d_inode(parent);
+               struct inode *parent_inode = d_inode(dentry->d_parent);
 
-               dput(parent);
                TP_fast_assign_fsid(btrfs_sb(inode->i_sb));
                __entry->ino            = btrfs_ino(BTRFS_I(inode));
                __entry->parent         = btrfs_ino(BTRFS_I(parent_inode));