diff mbox series

[v2,10/15] btrfs: add a global per cpu counter to track number of used extent maps

Message ID c52817a5221e712a7b3cb3686496eed82d9e04ce.1712837044.git.fdmanana@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: add a shrinker for extent maps | expand

Commit Message

Filipe Manana April 11, 2024, 4:19 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

Add a per cpu counter that tracks the total number of extent maps that are
in extent trees of inodes that belong to fs trees. This is going to be
used in an upcoming change that adds a shrinker for extent maps. Only
extent maps for fs trees are considered, because for special trees such as
the data relocation tree we don't want to evict their extent maps which
are critical for the relocation to work, and since those are limited, it's
not a concern to have them in memory during the relocation of a block
group. Another case are extent maps for free space cache inodes, which
must always remain in memory, but those are limited (there's only one per
free space cache inode, which means one per block group).

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/disk-io.c    |  6 ++++++
 fs/btrfs/extent_map.c | 17 +++++++++++++++++
 fs/btrfs/fs.h         |  2 ++
 3 files changed, 25 insertions(+)

Comments

kernel test robot April 15, 2024, 2:47 a.m. UTC | #1
Hello,

kernel test robot noticed "EIP:__percpu_counter_sum" on:

commit: b1c708ad024484a86a493ac9b1c94ba55ed9aec5 ("[PATCH v2 10/15] btrfs: add a global per cpu counter to track number of used extent maps")
url: https://github.com/intel-lab-lkp/linux/commits/fdmanana-kernel-org/btrfs-pass-an-inode-to-btrfs_add_extent_mapping/20240412-015132
base: https://git.kernel.org/cgit/linux/kernel/git/kdave/linux.git for-next
patch link: https://lore.kernel.org/all/c52817a5221e712a7b3cb3686496eed82d9e04ce.1712837044.git.fdmanana@suse.com/
patch subject: [PATCH v2 10/15] btrfs: add a global per cpu counter to track number of used extent maps

in testcase: boot

compiler: clang-17
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

(please refer to attached dmesg/kmsg for entire log/backtrace)


+---------------------------------------------------+------------+------------+
|                                                   | a4dd4472f7 | b1c708ad02 |
+---------------------------------------------------+------------+------------+
| INFO:trying_to_register_non-static_key            | 0          | 6          |
| BUG:unable_to_handle_page_fault_for_address       | 0          | 6          |
| Oops:#[##]                                        | 0          | 6          |
| EIP:__percpu_counter_sum                          | 0          | 6          |
| Kernel_panic-not_syncing:Fatal_exception          | 0          | 6          |
+---------------------------------------------------+------------+------------+


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/202404151034.cd36195c-oliver.sang@intel.com


[  201.010606][  T168] INFO: trying to register non-static key.
[  201.011499][  T168] The code is fine but needs lockdep annotation, or maybe
[  201.012269][  T168] you didn't initialize this object before use?
[  201.012951][  T168] turning off the locking correctness validator.
[  201.013663][  T168] CPU: 1 PID: 168 Comm: mount Tainted: G        W        N 6.9.0-rc3-00121-gb1c708ad0244 #1
[  201.014742][  T168] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[  201.015907][  T168] Call Trace:
[ 201.016332][ T168] dump_stack_lvl (lib/dump_stack.c:116) 
[ 201.016878][ T168] dump_stack (lib/dump_stack.c:123) 
[ 201.017392][ T168] assign_lock_key (kernel/locking/lockdep.c:?) 
[ 201.017966][ T168] register_lock_class (kernel/locking/lockdep.c:?) 
[ 201.018604][ T168] __lock_acquire (kernel/locking/lockdep.c:5014) 
[ 201.019210][ T168] ? __slab_free (mm/slub.c:4099) 
[ 201.019799][ T168] ? kern_path (fs/namei.c:2625) 
[ 201.020345][ T168] ? kmem_cache_free (mm/slub.c:4233 mm/slub.c:4281 mm/slub.c:4344) 
[ 201.020984][ T168] ? kern_path (fs/namei.c:2625) 
[ 201.021555][ T168] ? kern_path (fs/namei.c:2625) 
[ 201.022098][ T168] ? kern_path (fs/namei.c:2625) 
[ 201.022623][ T168] ? lock_release (kernel/locking/lockdep.c:5244) 
[ 201.023186][ T168] lock_acquire (kernel/locking/lockdep.c:5754) 
[ 201.023827][ T168] ? __percpu_counter_sum (lib/percpu_counter.c:?) 
[ 201.024440][ T168] ? mutex_unlock (kernel/locking/mutex.c:549) 
[ 201.024984][ T168] _raw_spin_lock_irqsave (include/linux/spinlock_api_smp.h:110 kernel/locking/spinlock.c:162) 
[ 201.025594][ T168] ? __percpu_counter_sum (lib/percpu_counter.c:?) 
[ 201.026203][ T168] __percpu_counter_sum (lib/percpu_counter.c:?) 
[ 201.026800][ T168] ? debug_mutex_init (include/linux/lockdep.h:135 include/linux/lockdep.h:142 kernel/locking/mutex-debug.c:87) 
[ 201.027371][ T168] btrfs_free_fs_info (fs/btrfs/disk-io.c:1272) 
[ 201.027986][ T168] btrfs_free_fs_context (fs/btrfs/super.c:2103) 
[ 201.028585][ T168] put_fs_context (fs/fs_context.c:522) 
[ 201.029136][ T168] btrfs_get_tree (include/linux/err.h:61 fs/btrfs/super.c:2051 fs/btrfs/super.c:2085) 
[ 201.029698][ T168] ? btrfs_parse_param (include/linux/fs_parser.h:73 fs/btrfs/super.c:272) 
[ 201.030293][ T168] ? security_capable (security/security.c:1036) 
[ 201.030869][ T168] vfs_get_tree (fs/super.c:1780) 
[ 201.031399][ T168] do_new_mount (fs/namespace.c:3352) 
[ 201.031950][ T168] ? security_capable (security/security.c:1036) 
[ 201.032538][ T168] path_mount (fs/namespace.c:3679) 
[ 201.033065][ T168] __ia32_sys_mount (fs/namespace.c:3692 fs/namespace.c:3898 fs/namespace.c:3875 fs/namespace.c:3875) 
[ 201.033643][ T168] do_int80_syscall_32 (arch/x86/entry/common.c:?) 
[ 201.034492][ T168] ? syscall_exit_to_user_mode (kernel/entry/common.c:221) 
[ 201.036999][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.037611][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.038214][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.038814][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.039445][ T168] ? irqentry_exit (kernel/entry/common.c:367) 
[ 201.040004][ T168] ? exc_page_fault (arch/x86/mm/fault.c:1567) 
[ 201.040579][ T168] entry_INT80_32 (arch/x86/entry/entry_32.S:944) 
[  201.041121][  T168] EIP: 0xb7dedd4e
[ 201.041595][ T168] Code: 90 66 90 66 90 66 90 66 90 66 90 90 57 56 53 8b 7c 24 20 8b 74 24 1c 8b 54 24 18 8b 4c 24 14 8b 5c 24 10 b8 15 00 00 00 cd 80 <5b> 5e 5f 3d 01 f0 ff ff 0f 83 64 7a f3 ff c3 66 90 90 57 56 53 8b
All code
========
   0:	90                   	nop
   1:	66 90                	xchg   %ax,%ax
   3:	66 90                	xchg   %ax,%ax
   5:	66 90                	xchg   %ax,%ax
   7:	66 90                	xchg   %ax,%ax
   9:	66 90                	xchg   %ax,%ax
   b:	90                   	nop
   c:	57                   	push   %rdi
   d:	56                   	push   %rsi
   e:	53                   	push   %rbx
   f:	8b 7c 24 20          	mov    0x20(%rsp),%edi
  13:	8b 74 24 1c          	mov    0x1c(%rsp),%esi
  17:	8b 54 24 18          	mov    0x18(%rsp),%edx
  1b:	8b 4c 24 14          	mov    0x14(%rsp),%ecx
  1f:	8b 5c 24 10          	mov    0x10(%rsp),%ebx
  23:	b8 15 00 00 00       	mov    $0x15,%eax
  28:	cd 80                	int    $0x80
  2a:*	5b                   	pop    %rbx		<-- trapping instruction
  2b:	5e                   	pop    %rsi
  2c:	5f                   	pop    %rdi
  2d:	3d 01 f0 ff ff       	cmp    $0xfffff001,%eax
  32:	0f 83 64 7a f3 ff    	jae    0xfffffffffff37a9c
  38:	c3                   	ret
  39:	66 90                	xchg   %ax,%ax
  3b:	90                   	nop
  3c:	57                   	push   %rdi
  3d:	56                   	push   %rsi
  3e:	53                   	push   %rbx
  3f:	8b                   	.byte 0x8b

Code starting with the faulting instruction
===========================================
   0:	5b                   	pop    %rbx
   1:	5e                   	pop    %rsi
   2:	5f                   	pop    %rdi
   3:	3d 01 f0 ff ff       	cmp    $0xfffff001,%eax
   8:	0f 83 64 7a f3 ff    	jae    0xfffffffffff37a72
   e:	c3                   	ret
   f:	66 90                	xchg   %ax,%ax
  11:	90                   	nop
  12:	57                   	push   %rdi
  13:	56                   	push   %rsi
  14:	53                   	push   %rbx
  15:	8b                   	.byte 0x8b
[  201.043677][  T168] EAX: ffffffda EBX: 004f14ca ECX: 004f14df EDX: 0210a960
[  201.044439][  T168] ESI: 00008000 EDI: 00000000 EBP: b7fa3474 ESP: bfbe8ad0
[  201.045227][  T168] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000292
[  201.046161][  T168] BUG: unable to handle page fault for address: 28a5a000
[  201.046968][  T168] #PF: supervisor read access in kernel mode
[  201.047675][  T168] #PF: error_code(0x0000) - not-present page
[  201.048368][  T168] *pdpt = 000000001a10a001 *pde = 0000000000000000
[  201.049105][  T168] Oops: 0000 [#1] SMP
[  201.049606][  T168] CPU: 1 PID: 168 Comm: mount Tainted: G        W        N 6.9.0-rc3-00121-gb1c708ad0244 #1
[  201.050803][  T168] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 201.052100][ T168] EIP: __percpu_counter_sum (lib/percpu_counter.c:147) 
[ 201.052770][ T168] Code: 90 90 90 89 d0 d3 e8 d3 e0 25 ff 00 00 00 74 2e 89 45 e8 f3 0f bc 4d e8 83 f9 07 77 21 8b 45 f0 8b 40 34 8b 34 8d f4 b5 9c c3 <8b> 04 06 89 c6 c1 fe 1f 01 c7 11 f3 83 f9 07 8d 49 01 75 c5 8b 45
All code
========
   0:	90                   	nop
   1:	90                   	nop
   2:	90                   	nop
   3:	89 d0                	mov    %edx,%eax
   5:	d3 e8                	shr    %cl,%eax
   7:	d3 e0                	shl    %cl,%eax
   9:	25 ff 00 00 00       	and    $0xff,%eax
   e:	74 2e                	je     0x3e
  10:	89 45 e8             	mov    %eax,-0x18(%rbp)
  13:	f3 0f bc 4d e8       	tzcnt  -0x18(%rbp),%ecx
  18:	83 f9 07             	cmp    $0x7,%ecx
  1b:	77 21                	ja     0x3e
  1d:	8b 45 f0             	mov    -0x10(%rbp),%eax
  20:	8b 40 34             	mov    0x34(%rax),%eax
  23:	8b 34 8d f4 b5 9c c3 	mov    -0x3c634a0c(,%rcx,4),%esi
  2a:*	8b 04 06             	mov    (%rsi,%rax,1),%eax		<-- trapping instruction
  2d:	89 c6                	mov    %eax,%esi
  2f:	c1 fe 1f             	sar    $0x1f,%esi
  32:	01 c7                	add    %eax,%edi
  34:	11 f3                	adc    %esi,%ebx
  36:	83 f9 07             	cmp    $0x7,%ecx
  39:	8d 49 01             	lea    0x1(%rcx),%ecx
  3c:	75 c5                	jne    0x3
  3e:	8b                   	.byte 0x8b
  3f:	45                   	rex.RB

Code starting with the faulting instruction
===========================================
   0:	8b 04 06             	mov    (%rsi,%rax,1),%eax
   3:	89 c6                	mov    %eax,%esi
   5:	c1 fe 1f             	sar    $0x1f,%esi
   8:	01 c7                	add    %eax,%edi
   a:	11 f3                	adc    %esi,%ebx
   c:	83 f9 07             	cmp    $0x7,%ecx
   f:	8d 49 01             	lea    0x1(%rcx),%ecx
  12:	75 c5                	jne    0xffffffffffffffd9
  14:	8b                   	.byte 0x8b
  15:	45                   	rex.RB
[  201.054977][  T168] EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000003
[  201.058373][  T168] ESI: 28a5a000 EDI: 00000000 EBP: ee833d88 ESP: ee833d70
[  201.059245][  T168] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 EFLAGS: 00010097
[  201.060208][  T168] CR0: 80050033 CR2: 28a5a000 CR3: 0502cfa0 CR4: 000406b0
[  201.061046][  T168] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[  201.061893][  T168] DR6: fffe0ff0 DR7: 00000400
[  201.062503][  T168] Call Trace:
[ 201.062978][ T168] ? __die_body (arch/x86/kernel/dumpstack.c:478 arch/x86/kernel/dumpstack.c:420) 
[ 201.067652][ T168] ? __die (arch/x86/kernel/dumpstack.c:434) 
[ 201.068186][ T168] ? page_fault_oops (arch/x86/mm/fault.c:709) 
[ 201.068788][ T168] ? __slab_free (mm/slub.c:4099) 
[ 201.069398][ T168] ? kernelmode_fixup_or_oops (arch/x86/mm/fault.c:767) 
[ 201.070107][ T168] ? __bad_area_nosemaphore (arch/x86/mm/fault.c:814) 
[ 201.070815][ T168] ? kern_path (fs/namei.c:2625) 
[ 201.071402][ T168] ? bad_area_nosemaphore (arch/x86/mm/fault.c:863) 
[ 201.072062][ T168] ? do_user_addr_fault (arch/x86/mm/fault.c:?) 
[ 201.072729][ T168] ? exc_page_fault (arch/x86/include/asm/irqflags.h:19 arch/x86/include/asm/irqflags.h:67 arch/x86/include/asm/irqflags.h:127 arch/x86/mm/fault.c:1513 arch/x86/mm/fault.c:1563) 
[ 201.073359][ T168] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518) 
[ 201.074135][ T168] ? handle_exception (arch/x86/entry/entry_32.S:1054) 
[ 201.074815][ T168] ? atomic_dec_and_mutex_lock (kernel/locking/mutex.c:548 kernel/locking/mutex.c:1153) 
[ 201.075553][ T168] ? rwsem_down_write_slowpath (include/trace/events/lock.h:95) 
[ 201.076301][ T168] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518) 
[ 201.077099][ T168] ? __percpu_counter_sum (lib/percpu_counter.c:147) 
[ 201.077771][ T168] ? rwsem_down_write_slowpath (include/trace/events/lock.h:95) 
[ 201.078512][ T168] ? pvclock_clocksource_read_nowd (arch/x86/mm/fault.c:1518) 
[ 201.079292][ T168] ? __percpu_counter_sum (lib/percpu_counter.c:147) 
[ 201.079968][ T168] btrfs_free_fs_info (fs/btrfs/disk-io.c:1272) 
[ 201.080615][ T168] btrfs_free_fs_context (fs/btrfs/super.c:2103) 
[ 201.081282][ T168] put_fs_context (fs/fs_context.c:522) 
[ 201.081910][ T168] btrfs_get_tree (include/linux/err.h:61 fs/btrfs/super.c:2051 fs/btrfs/super.c:2085) 
[ 201.082549][ T168] ? btrfs_parse_param (include/linux/fs_parser.h:73 fs/btrfs/super.c:272) 
[ 201.083205][ T168] ? security_capable (security/security.c:1036) 
[ 201.083857][ T168] vfs_get_tree (fs/super.c:1780) 
[ 201.084444][ T168] do_new_mount (fs/namespace.c:3352) 
[ 201.085054][ T168] ? security_capable (security/security.c:1036) 
[ 201.085690][ T168] path_mount (fs/namespace.c:3679) 
[ 201.086281][ T168] __ia32_sys_mount (fs/namespace.c:3692 fs/namespace.c:3898 fs/namespace.c:3875 fs/namespace.c:3875) 
[ 201.089463][ T168] do_int80_syscall_32 (arch/x86/entry/common.c:?) 
[ 201.090154][ T168] ? syscall_exit_to_user_mode (kernel/entry/common.c:221) 
[ 201.090895][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.091578][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.092250][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.092939][ T168] ? do_int80_syscall_32 (arch/x86/entry/common.c:278) 
[ 201.093621][ T168] ? irqentry_exit (kernel/entry/common.c:367) 
[ 201.094251][ T168] ? exc_page_fault (arch/x86/mm/fault.c:1567) 
[ 201.094913][ T168] entry_INT80_32 (arch/x86/entry/entry_32.S:944) 
[  201.095560][  T168] EIP: 0xb7dedd4e
[ 201.096066][ T168] Code: 90 66 90 66 90 66 90 66 90 66 90 90 57 56 53 8b 7c 24 20 8b 74 24 1c 8b 54 24 18 8b 4c 24 14 8b 5c 24 10 b8 15 00 00 00 cd 80 <5b> 5e 5f 3d 01 f0 ff ff 0f 83 64 7a f3 ff c3 66 90 90 57 56 53 8b
All code
========
   0:	90                   	nop
   1:	66 90                	xchg   %ax,%ax
   3:	66 90                	xchg   %ax,%ax
   5:	66 90                	xchg   %ax,%ax
   7:	66 90                	xchg   %ax,%ax
   9:	66 90                	xchg   %ax,%ax
   b:	90                   	nop
   c:	57                   	push   %rdi
   d:	56                   	push   %rsi
   e:	53                   	push   %rbx
   f:	8b 7c 24 20          	mov    0x20(%rsp),%edi
  13:	8b 74 24 1c          	mov    0x1c(%rsp),%esi
  17:	8b 54 24 18          	mov    0x18(%rsp),%edx
  1b:	8b 4c 24 14          	mov    0x14(%rsp),%ecx
  1f:	8b 5c 24 10          	mov    0x10(%rsp),%ebx
  23:	b8 15 00 00 00       	mov    $0x15,%eax
  28:	cd 80                	int    $0x80
  2a:*	5b                   	pop    %rbx		<-- trapping instruction
  2b:	5e                   	pop    %rsi
  2c:	5f                   	pop    %rdi
  2d:	3d 01 f0 ff ff       	cmp    $0xfffff001,%eax
  32:	0f 83 64 7a f3 ff    	jae    0xfffffffffff37a9c
  38:	c3                   	ret
  39:	66 90                	xchg   %ax,%ax
  3b:	90                   	nop
  3c:	57                   	push   %rdi
  3d:	56                   	push   %rsi
  3e:	53                   	push   %rbx
  3f:	8b                   	.byte 0x8b

Code starting with the faulting instruction
===========================================
   0:	5b                   	pop    %rbx
   1:	5e                   	pop    %rsi
   2:	5f                   	pop    %rdi
   3:	3d 01 f0 ff ff       	cmp    $0xfffff001,%eax
   8:	0f 83 64 7a f3 ff    	jae    0xfffffffffff37a72
   e:	c3                   	ret
   f:	66 90                	xchg   %ax,%ax
  11:	90                   	nop
  12:	57                   	push   %rdi
  13:	56                   	push   %rsi
  14:	53                   	push   %rbx
  15:	8b                   	.byte 0x8b


The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20240415/202404151034.cd36195c-oliver.sang@intel.com
diff mbox series

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 0474e9b6d302..3c2d35b2062e 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1269,6 +1269,8 @@  void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
 	percpu_counter_destroy(&fs_info->delalloc_bytes);
 	percpu_counter_destroy(&fs_info->ordered_bytes);
+	ASSERT(percpu_counter_sum_positive(&fs_info->evictable_extent_maps) == 0);
+	percpu_counter_destroy(&fs_info->evictable_extent_maps);
 	percpu_counter_destroy(&fs_info->dev_replace.bio_counter);
 	btrfs_free_csum_hash(fs_info);
 	btrfs_free_stripe_hash_table(fs_info);
@@ -2848,6 +2850,10 @@  static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
 	if (ret)
 		return ret;
 
+	ret = percpu_counter_init(&fs_info->evictable_extent_maps, 0, GFP_KERNEL);
+	if (ret)
+		return ret;
+
 	ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
 	if (ret)
 		return ret;
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 97a8e0484415..2fcf28148a81 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -76,6 +76,14 @@  static u64 range_end(u64 start, u64 len)
 	return start + len;
 }
 
+static void dec_evictable_extent_maps(struct btrfs_inode *inode)
+{
+	struct btrfs_fs_info *fs_info = inode->root->fs_info;
+
+	if (!btrfs_is_testing(fs_info) && is_fstree(btrfs_root_id(inode->root)))
+		percpu_counter_dec(&fs_info->evictable_extent_maps);
+}
+
 static int tree_insert(struct rb_root_cached *root, struct extent_map *em)
 {
 	struct rb_node **p = &root->rb_root.rb_node;
@@ -259,6 +267,7 @@  static void try_merge_map(struct btrfs_inode *inode, struct extent_map *em)
 			rb_erase_cached(&merge->rb_node, &tree->map);
 			RB_CLEAR_NODE(&merge->rb_node);
 			free_extent_map(merge);
+			dec_evictable_extent_maps(inode);
 		}
 	}
 
@@ -273,6 +282,7 @@  static void try_merge_map(struct btrfs_inode *inode, struct extent_map *em)
 		em->generation = max(em->generation, merge->generation);
 		em->flags |= EXTENT_FLAG_MERGED;
 		free_extent_map(merge);
+		dec_evictable_extent_maps(inode);
 	}
 }
 
@@ -372,6 +382,8 @@  static int add_extent_mapping(struct btrfs_inode *inode,
 			      struct extent_map *em, int modified)
 {
 	struct extent_map_tree *tree = &inode->extent_tree;
+	struct btrfs_root *root = inode->root;
+	struct btrfs_fs_info *fs_info = root->fs_info;
 	int ret;
 
 	lockdep_assert_held_write(&tree->lock);
@@ -382,6 +394,9 @@  static int add_extent_mapping(struct btrfs_inode *inode,
 
 	setup_extent_mapping(inode, em, modified);
 
+	if (!btrfs_is_testing(fs_info) && is_fstree(btrfs_root_id(root)))
+		percpu_counter_inc(&fs_info->evictable_extent_maps);
+
 	return 0;
 }
 
@@ -467,6 +482,8 @@  void remove_extent_mapping(struct btrfs_inode *inode, struct extent_map *em)
 	if (!(em->flags & EXTENT_FLAG_LOGGING))
 		list_del_init(&em->list);
 	RB_CLEAR_NODE(&em->rb_node);
+
+	dec_evictable_extent_maps(inode);
 }
 
 static void replace_extent_mapping(struct btrfs_inode *inode,
diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
index 93f5c57ea4e3..534d30dafe32 100644
--- a/fs/btrfs/fs.h
+++ b/fs/btrfs/fs.h
@@ -630,6 +630,8 @@  struct btrfs_fs_info {
 	s32 dirty_metadata_batch;
 	s32 delalloc_batch;
 
+	struct percpu_counter evictable_extent_maps;
+
 	/* Protected by 'trans_lock'. */
 	struct list_head dirty_cowonly_roots;