Message ID | 168599179360.70911.4102140966715923751.stgit@pro.pro (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | mm: Make unregistration of super_block shrinker more faster | expand |
Hello, kernel test robot noticed "INFO:trying_to_register_non-static_key" on: commit: 107ed33204f77282d67b90f5c37f34c4b1ec9ffb ("[PATCH v2 2/3] mm: Split unregister_shrinker() in fast and slow part") url: https://github.com/intel-lab-lkp/linux/commits/Kirill-Tkhai/mm-vmscan-move-shrinker_debugfs_remove-before-synchronize_srcu/20230606-030419 base: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git f8dba31b0a826e691949cd4fdfa5c30defaac8c5 patch link: https://lore.kernel.org/all/168599179360.70911.4102140966715923751.stgit@pro.pro/ patch subject: [PATCH v2 2/3] mm: Split unregister_shrinker() in fast and slow part in testcase: boot compiler: clang-15 test machine: qemu-system-i386 -enable-kvm -cpu SandyBridge -smp 2 -m 4G (please refer to attached dmesg/kmsg for entire log/backtrace) If you fix the issue, kindly add following tag | Reported-by: kernel test robot <oliver.sang@intel.com> | Closes: https://lore.kernel.org/oe-lkp/202306071000.4ad4e5ba-oliver.sang@intel.com [ 0.538549][ T0] INFO: trying to register non-static key. [ 0.539249][ T0] The code is fine but needs lockdep annotation, or maybe [ 0.539385][ T0] you didn't initialize this object before use? [ 0.539385][ T0] turning off the locking correctness validator. [ 0.539385][ T0] CPU: 0 PID: 0 Comm: swapper Not tainted 6.4.0-rc5-00004-g107ed33204f7 #1 [ 0.539385][ T0] Call Trace: [ 0.539385][ T0] dump_stack_lvl (??:?) [ 0.539385][ T0] dump_stack (??:?) [ 0.539385][ T0] assign_lock_key (lockdep.c:?) [ 0.539385][ T0] register_lock_class (lockdep.c:?) [ 0.539385][ T0] __lock_acquire (lockdep.c:?) [ 0.539385][ T0] ? lock_acquire (??:?) [ 0.539385][ T0] ? register_shrinker_prepared (??:?) [ 0.539385][ T0] ? __might_resched (??:?) [ 0.539385][ T0] lock_acquire (??:?) [ 0.539385][ T0] ? register_shrinker_prepared (??:?) [ 0.539385][ T0] ? __might_resched (??:?) [ 0.539385][ T0] down_write (??:?) [ 0.539385][ T0] ? register_shrinker_prepared (??:?) [ 0.539385][ T0] register_shrinker_prepared (??:?) [ 0.539385][ T0] sget_fc (??:?) [ 0.539385][ T0] ? kill_litter_super (??:?) [ 0.539385][ T0] ? shmem_reconfigure (shmem.c:?) [ 0.539385][ T0] get_tree_nodev (??:?) [ 0.539385][ T0] shmem_get_tree (shmem.c:?) [ 0.539385][ T0] vfs_get_tree (??:?) [ 0.539385][ T0] vfs_kern_mount (??:?) [ 0.539385][ T0] kern_mount (??:?) [ 0.539385][ T0] shmem_init (??:?) [ 0.539385][ T0] mnt_init (??:?) [ 0.539385][ T0] vfs_caches_init (??:?) [ 0.539385][ T0] start_kernel (??:?) [ 0.539385][ T0] i386_start_kernel (??:?) [ 0.539385][ T0] startup_32_smp (??:?) [ 0.539391][ T0] ------------[ cut here ]------------ [ 0.540097][ T0] DEBUG_RWSEMS_WARN_ON(sem->magic != sem): count = 0x1, magic = 0x0, owner = 0x81d77c00, curr 0x81d77c00, list not empty [ 0.540405][ T0] WARNING: CPU: 0 PID: 0 at kernel/locking/rwsem.c:1364 up_write (??:?) [ 0.541389][ T0] Modules linked in: [ 0.542390][ T0] CPU: 0 PID: 0 Comm: swapper Not tainted 6.4.0-rc5-00004-g107ed33204f7 #1 [ 0.543389][ T0] EIP: up_write (??:?) [ 0.543920][ T0] Code: ee 8f c6 81 39 c1 74 05 bb 7f 8b c4 81 53 52 ff 74 24 08 57 ff 74 24 14 68 44 a3 cb 81 68 6d 1a ce 81 e8 32 68 fb ff 83 c4 1c <0f> 0b 39 f7 0f 85 a8 fe ff ff e9 a8 fe ff ff 0f 0b e9 db fe ff ff All code ======== 0: ee out %al,(%dx) 1: 8f c6 pop %rsi 3: 81 39 c1 74 05 bb cmpl $0xbb0574c1,(%rcx) 9: 7f 8b jg 0xffffffffffffff96 b: c4 81 53 52 (bad) f: ff 74 24 08 pushq 0x8(%rsp) 13: 57 push %rdi 14: ff 74 24 14 pushq 0x14(%rsp) 18: 68 44 a3 cb 81 pushq $0xffffffff81cba344 1d: 68 6d 1a ce 81 pushq $0xffffffff81ce1a6d 22: e8 32 68 fb ff callq 0xfffffffffffb6859 27: 83 c4 1c add $0x1c,%esp 2a:* 0f 0b ud2 <-- trapping instruction 2c: 39 f7 cmp %esi,%edi 2e: 0f 85 a8 fe ff ff jne 0xfffffffffffffedc 34: e9 a8 fe ff ff jmpq 0xfffffffffffffee1 39: 0f 0b ud2 3b: e9 db fe ff ff jmpq 0xffffffffffffff1b Code starting with the faulting instruction =========================================== 0: 0f 0b ud2 2: 39 f7 cmp %esi,%edi 4: 0f 85 a8 fe ff ff jne 0xfffffffffffffeb2 a: e9 a8 fe ff ff jmpq 0xfffffffffffffeb7 f: 0f 0b ud2 11: e9 db fe ff ff jmpq 0xfffffffffffffef1 [ 0.544391][ T0] EAX: e6de3575 EBX: 81c48b7f ECX: e6de3575 EDX: 81d67dd0 [ 0.545388][ T0] ESI: 831f4c4c EDI: 00000000 EBP: 81d67ed0 ESP: 81d67ea8 [ 0.546389][ T0] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00210292 [ 0.547388][ T0] CR0: 80050033 CR2: ffd98000 CR3: 02280000 CR4: 00040690 [ 0.548392][ T0] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 0.549388][ T0] DR6: fffe0ff0 DR7: 00000400 [ 0.549947][ T0] Call Trace: [ 0.550391][ T0] ? show_regs (??:?) [ 0.550910][ T0] ? up_write (??:?) [ 0.551389][ T0] ? __warn (??:?) [ 0.551869][ T0] ? up_write (??:?) [ 0.552389][ T0] ? up_write (??:?) [ 0.552921][ T0] ? report_bug (??:?) [ 0.553390][ T0] ? exc_overflow (??:?) [ 0.554390][ T0] ? handle_bug (traps.c:?) [ 0.554923][ T0] ? exc_invalid_op (??:?) [ 0.555390][ T0] ? handle_exception (init_task.c:?) [ 0.556022][ T0] ? arch_report_meminfo (??:?) [ 0.556389][ T0] ? exc_overflow (??:?) [ 0.557389][ T0] ? up_write (??:?) [ 0.557927][ T0] ? exc_overflow (??:?) [ 0.558389][ T0] ? up_write (??:?) [ 0.558904][ T0] register_shrinker_prepared (??:?) [ 0.559390][ T0] sget_fc (??:?) [ 0.559887][ T0] ? kill_litter_super (??:?) [ 0.560390][ T0] ? shmem_reconfigure (shmem.c:?) [ 0.561390][ T0] get_tree_nodev (??:?) [ 0.562390][ T0] shmem_get_tree (shmem.c:?) [ 0.563390][ T0] vfs_get_tree (??:?) [ 0.563914][ T0] vfs_kern_mount (??:?) [ 0.564390][ T0] kern_mount (??:?) [ 0.564908][ T0] shmem_init (??:?) [ 0.565389][ T0] mnt_init (??:?) [ 0.565892][ T0] vfs_caches_init (??:?) [ 0.566390][ T0] start_kernel (??:?) [ 0.567390][ T0] i386_start_kernel (??:?) [ 0.568009][ T0] startup_32_smp (??:?) [ 0.568392][ T0] irq event stamp: 1613 [ 0.568888][ T0] hardirqs last enabled at (1613): _raw_spin_unlock_irqrestore (??:?) [ 0.569389][ T0] hardirqs last disabled at (1612): _raw_spin_lock_irqsave (??:?) [ 0.570389][ T0] softirqs last enabled at (1480): do_softirq_own_stack (??:?) [ 0.571389][ T0] softirqs last disabled at (1473): do_softirq_own_stack (??:?) [ 0.572389][ T0] ---[ end trace 0000000000000000 ]--- [ 0.573889][ T0] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0 [ 0.574391][ T0] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0 To reproduce: # build kernel cd linux cp config-6.4.0-rc5-00004-g107ed33204f7 .config make HOSTCC=clang-15 CC=clang-15 ARCH=i386 olddefconfig prepare modules_prepare bzImage modules make HOSTCC=clang-15 CC=clang-15 ARCH=i386 INSTALL_MOD_PATH=<mod-install-dir> modules_install cd <mod-install-dir> find lib/ | cpio -o -H newc --quiet | gzip > modules.cgz git clone https://github.com/intel/lkp-tests.git cd lkp-tests bin/lkp qemu -k <bzImage> -m modules.cgz job-script # job-script is attached in this email # if come across any failure that blocks the test, # please remove ~/.lkp and /lkp dir to run from a clean state.
On Wed, Jun 07, 2023 at 12:49:55PM +0800, kernel test robot wrote: > > Hello, > > kernel test robot noticed "INFO:trying_to_register_non-static_key" on: > > commit: 107ed33204f77282d67b90f5c37f34c4b1ec9ffb ("[PATCH v2 2/3] mm: Split unregister_shrinker() in fast and slow part") > url: https://github.com/intel-lab-lkp/linux/commits/Kirill-Tkhai/mm-vmscan-move-shrinker_debugfs_remove-before-synchronize_srcu/20230606-030419 > base: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git f8dba31b0a826e691949cd4fdfa5c30defaac8c5 > patch link: https://lore.kernel.org/all/168599179360.70911.4102140966715923751.stgit@pro.pro/ > patch subject: [PATCH v2 2/3] mm: Split unregister_shrinker() in fast and slow part > > in testcase: boot > > compiler: clang-15 > test machine: qemu-system-i386 -enable-kvm -cpu SandyBridge -smp 2 -m 4G > > (please refer to attached dmesg/kmsg for entire log/backtrace) > > > > If you fix the issue, kindly add following tag > | Reported-by: kernel test robot <oliver.sang@intel.com> > | Closes: https://lore.kernel.org/oe-lkp/202306071000.4ad4e5ba-oliver.sang@intel.com Sorry the stacktrace in the report was broken due to a toolchain issue in the bot. Please check the correct stacktrace as below: [ 0.538549][ T0] INFO: trying to register non-static key. [ 0.539249][ T0] The code is fine but needs lockdep annotation, or maybe [ 0.539385][ T0] you didn't initialize this object before use? [ 0.539385][ T0] turning off the locking correctness validator. [ 0.539385][ T0] CPU: 0 PID: 0 Comm: swapper Not tainted 6.4.0-rc5-00004-g107ed33204f7 #1 [ 0.539385][ T0] Call Trace: [ 0.539385][ T0] dump_stack_lvl (lib/dump_stack.c:?) [ 0.539385][ T0] dump_stack (lib/dump_stack.c:113) [ 0.539385][ T0] assign_lock_key (kernel/locking/lockdep.c:?) [ 0.539385][ T0] register_lock_class (kernel/locking/lockdep.c:?) [ 0.539385][ T0] __lock_acquire (kernel/locking/lockdep.c:4965) [ 0.539385][ T0] ? lock_acquire (kernel/locking/lockdep.c:5705) [ 0.539385][ T0] ? register_shrinker_prepared (mm/vmscan.c:760) [ 0.539385][ T0] ? __might_resched (kernel/sched/core.c:10115) [ 0.539385][ T0] lock_acquire (kernel/locking/lockdep.c:5705) [ 0.539385][ T0] ? register_shrinker_prepared (mm/vmscan.c:762) [ 0.539385][ T0] ? __might_resched (kernel/sched/core.c:10115) [ 0.539385][ T0] down_write (kernel/locking/rwsem.c:1573) [ 0.539385][ T0] ? register_shrinker_prepared (mm/vmscan.c:762) [ 0.539385][ T0] register_shrinker_prepared (mm/vmscan.c:762) [ 0.539385][ T0] sget_fc (fs/super.c:616) [ 0.539385][ T0] ? kill_litter_super (fs/super.c:1121) [ 0.539385][ T0] ? shmem_reconfigure (mm/shmem.c:3791) [ 0.539385][ T0] get_tree_nodev (fs/super.c:1144) [ 0.539385][ T0] shmem_get_tree (mm/shmem.c:3879) [ 0.539385][ T0] vfs_get_tree (fs/super.c:1511) [ 0.539385][ T0] vfs_kern_mount (fs/namespace.c:1036 fs/namespace.c:1065) [ 0.539385][ T0] kern_mount (fs/namespace.c:4455) [ 0.539385][ T0] shmem_init (mm/shmem.c:4106) [ 0.539385][ T0] mnt_init (fs/namespace.c:4440) [ 0.539385][ T0] vfs_caches_init (fs/dcache.c:3355) [ 0.539385][ T0] start_kernel (init/main.c:1071) [ 0.539385][ T0] i386_start_kernel (arch/x86/kernel/head32.c:56) [ 0.539385][ T0] startup_32_smp (arch/x86/kernel/head_32.S:319) [ 0.539391][ T0] ------------[ cut here ]------------ [ 0.540097][ T0] DEBUG_RWSEMS_WARN_ON(sem->magic != sem): count = 0x1, magic = 0x0, owner = 0x81d77c00, curr 0x81d77c00, list not empty [ 0.540405][ T0] WARNING: CPU: 0 PID: 0 at kernel/locking/rwsem.c:1364 up_write (kernel/locking/rwsem.c:1364) [ 0.541389][ T0] Modules linked in: [ 0.542390][ T0] CPU: 0 PID: 0 Comm: swapper Not tainted 6.4.0-rc5-00004-g107ed33204f7 #1 [ 0.543389][ T0] EIP: up_write (kernel/locking/rwsem.c:1364) [ 0.543920][ T0] Code: ee 8f c6 81 39 c1 74 05 bb 7f 8b c4 81 53 52 ff 74 24 08 57 ff 74 24 14 68 44 a3 cb 81 68 6d 1a ce 81 e8 32 68 fb ff 83 c4 1c <0f> 0b 39 f7 0f 85 a8 fe ff ff e9 a8 fe ff ff 0f 0b e9 db fe ff ff All code ======== 0: ee out %al,(%dx) 1: 8f c6 pop %rsi 3: 81 39 c1 74 05 bb cmpl $0xbb0574c1,(%rcx) 9: 7f 8b jg 0xffffffffffffff96 b: c4 81 53 52 (bad) f: ff 74 24 08 push 0x8(%rsp) 13: 57 push %rdi 14: ff 74 24 14 push 0x14(%rsp) 18: 68 44 a3 cb 81 push $0xffffffff81cba344 1d: 68 6d 1a ce 81 push $0xffffffff81ce1a6d 22: e8 32 68 fb ff call 0xfffffffffffb6859 27: 83 c4 1c add $0x1c,%esp 2a:* 0f 0b ud2 <-- trapping instruction 2c: 39 f7 cmp %esi,%edi 2e: 0f 85 a8 fe ff ff jne 0xfffffffffffffedc 34: e9 a8 fe ff ff jmp 0xfffffffffffffee1 39: 0f 0b ud2 3b: e9 db fe ff ff jmp 0xffffffffffffff1b Code starting with the faulting instruction =========================================== 0: 0f 0b ud2 2: 39 f7 cmp %esi,%edi 4: 0f 85 a8 fe ff ff jne 0xfffffffffffffeb2 a: e9 a8 fe ff ff jmp 0xfffffffffffffeb7 f: 0f 0b ud2 11: e9 db fe ff ff jmp 0xfffffffffffffef1 [ 0.544391][ T0] EAX: e6de3575 EBX: 81c48b7f ECX: e6de3575 EDX: 81d67dd0 [ 0.545388][ T0] ESI: 831f4c4c EDI: 00000000 EBP: 81d67ed0 ESP: 81d67ea8 [ 0.546389][ T0] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 EFLAGS: 00210292 [ 0.547388][ T0] CR0: 80050033 CR2: ffd98000 CR3: 02280000 CR4: 00040690 [ 0.548392][ T0] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 0.549388][ T0] DR6: fffe0ff0 DR7: 00000400 [ 0.549947][ T0] Call Trace: [ 0.550391][ T0] ? show_regs (arch/x86/kernel/dumpstack.c:478) [ 0.550910][ T0] ? up_write (kernel/locking/rwsem.c:1364) [ 0.551389][ T0] ? __warn (kernel/panic.c:235 kernel/panic.c:673) [ 0.551869][ T0] ? up_write (kernel/locking/rwsem.c:1364) [ 0.552389][ T0] ? up_write (kernel/locking/rwsem.c:1364) [ 0.552921][ T0] ? report_bug (lib/bug.c:199) [ 0.553390][ T0] ? exc_overflow (arch/x86/kernel/traps.c:337) [ 0.554390][ T0] ? handle_bug (arch/x86/kernel/traps.c:324) [ 0.554923][ T0] ? exc_invalid_op (arch/x86/kernel/traps.c:345) [ 0.555390][ T0] ? handle_exception (arch/x86/entry/entry_32.S:1076) [ 0.556022][ T0] ? arch_report_meminfo (arch/x86/mm/pat/set_memory.c:112) [ 0.556389][ T0] ? exc_overflow (arch/x86/kernel/traps.c:337) [ 0.557389][ T0] ? up_write (kernel/locking/rwsem.c:1364) [ 0.557927][ T0] ? exc_overflow (arch/x86/kernel/traps.c:337) [ 0.558389][ T0] ? up_write (kernel/locking/rwsem.c:1364) [ 0.558904][ T0] register_shrinker_prepared (mm/vmscan.c:765) [ 0.559390][ T0] sget_fc (fs/super.c:616) [ 0.559887][ T0] ? kill_litter_super (fs/super.c:1121) [ 0.560390][ T0] ? shmem_reconfigure (mm/shmem.c:3791) [ 0.561390][ T0] get_tree_nodev (fs/super.c:1144) [ 0.562390][ T0] shmem_get_tree (mm/shmem.c:3879) [ 0.563390][ T0] vfs_get_tree (fs/super.c:1511) [ 0.563914][ T0] vfs_kern_mount (fs/namespace.c:1036 fs/namespace.c:1065) [ 0.564390][ T0] kern_mount (fs/namespace.c:4455) [ 0.564908][ T0] shmem_init (mm/shmem.c:4106) [ 0.565389][ T0] mnt_init (fs/namespace.c:4440) [ 0.565892][ T0] vfs_caches_init (fs/dcache.c:3355) [ 0.566390][ T0] start_kernel (init/main.c:1071) [ 0.567390][ T0] i386_start_kernel (arch/x86/kernel/head32.c:56) [ 0.568009][ T0] startup_32_smp (arch/x86/kernel/head_32.S:319) [ 0.568392][ T0] irq event stamp: 1613 [ 0.568888][ T0] hardirqs last enabled at (1613): _raw_spin_unlock_irqrestore (arch/x86/include/asm/irqflags.h:42 arch/x86/include/asm/irqflags.h:77 arch/x86/include/asm/irqflags.h:135 include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194) [ 0.569389][ T0] hardirqs last disabled at (1612): _raw_spin_lock_irqsave (arch/x86/include/asm/preempt.h:80 include/linux/spinlock_api_smp.h:109 kernel/locking/spinlock.c:162) [ 0.570389][ T0] softirqs last enabled at (1480): do_softirq_own_stack (arch/x86/kernel/irq_32.c:57 arch/x86/kernel/irq_32.c:147) [ 0.571389][ T0] softirqs last disabled at (1473): do_softirq_own_stack (arch/x86/kernel/irq_32.c:57 arch/x86/kernel/irq_32.c:147) [ 0.572389][ T0] ---[ end trace 0000000000000000 ]---
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 224293b2dd06..1cc572fa6070 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -4,6 +4,7 @@ #include <linux/atomic.h> #include <linux/types.h> +#include <linux/rwsem.h> /* * This struct is used to pass information from page reclaim to the shrinkers. @@ -83,6 +84,7 @@ struct shrinker { #endif /* objs pending delete, per node */ atomic_long_t *nr_deferred; + struct rw_semaphore rwsem; }; #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ @@ -102,6 +104,8 @@ extern void register_shrinker_prepared(struct shrinker *shrinker); extern int __printf(2, 3) register_shrinker(struct shrinker *shrinker, const char *fmt, ...); extern void unregister_shrinker(struct shrinker *shrinker); +extern void unregister_shrinker_delayed_initiate(struct shrinker *shrinker); +extern void unregister_shrinker_delayed_finalize(struct shrinker *shrinker); extern void free_prealloced_shrinker(struct shrinker *shrinker); extern void synchronize_shrinkers(void); diff --git a/mm/vmscan.c b/mm/vmscan.c index a773e97e152e..f24fd58dcc2a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -706,6 +706,7 @@ static int __prealloc_shrinker(struct shrinker *shrinker) if (!shrinker->nr_deferred) return -ENOMEM; + init_rwsem(&shrinker->rwsem); return 0; } @@ -757,7 +758,9 @@ void register_shrinker_prepared(struct shrinker *shrinker) { mutex_lock(&shrinker_mutex); list_add_tail_rcu(&shrinker->list, &shrinker_list); + down_write(&shrinker->rwsem); shrinker->flags |= SHRINKER_REGISTERED; + up_write(&shrinker->rwsem); shrinker_debugfs_add(shrinker); mutex_unlock(&shrinker_mutex); } @@ -802,7 +805,7 @@ EXPORT_SYMBOL(register_shrinker); /* * Remove one */ -void unregister_shrinker(struct shrinker *shrinker) +void unregister_shrinker_delayed_initiate(struct shrinker *shrinker) { struct dentry *debugfs_entry; int debugfs_id; @@ -812,20 +815,33 @@ void unregister_shrinker(struct shrinker *shrinker) mutex_lock(&shrinker_mutex); list_del_rcu(&shrinker->list); + down_write(&shrinker->rwsem); shrinker->flags &= ~SHRINKER_REGISTERED; + up_write(&shrinker->rwsem); if (shrinker->flags & SHRINKER_MEMCG_AWARE) unregister_memcg_shrinker(shrinker); debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id); mutex_unlock(&shrinker_mutex); shrinker_debugfs_remove(debugfs_entry, debugfs_id); +} +EXPORT_SYMBOL(unregister_shrinker_delayed_initiate); +void unregister_shrinker_delayed_finalize(struct shrinker *shrinker) +{ atomic_inc(&shrinker_srcu_generation); synchronize_srcu(&shrinker_srcu); kfree(shrinker->nr_deferred); shrinker->nr_deferred = NULL; } +EXPORT_SYMBOL(unregister_shrinker_delayed_finalize); + +void unregister_shrinker(struct shrinker *shrinker) +{ + unregister_shrinker_delayed_initiate(shrinker); + unregister_shrinker_delayed_finalize(shrinker); +} EXPORT_SYMBOL(unregister_shrinker); /** @@ -856,9 +872,15 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, : SHRINK_BATCH; long scanned = 0, next_deferred; + if (!down_read_trylock(&shrinker->rwsem)) + return 0; + if (!(shrinker->flags & SHRINKER_REGISTERED)) + goto unlock; freeable = shrinker->count_objects(shrinker, shrinkctl); - if (freeable == 0 || freeable == SHRINK_EMPTY) - return freeable; + if (freeable == 0 || freeable == SHRINK_EMPTY) { + freed = freeable; + goto unlock; + } /* * copy the current shrinker scan count into a local variable @@ -937,6 +959,8 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, new_nr = add_nr_deferred(next_deferred, shrinker, shrinkctl); trace_mm_shrink_slab_end(shrinker, shrinkctl->nid, freed, nr, new_nr, total_scan); +unlock: + up_read(&shrinker->rwsem); return freed; } @@ -968,9 +992,8 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid, struct shrinker *shrinker; shrinker = idr_find(&shrinker_idr, i); - if (unlikely(!shrinker || !(shrinker->flags & SHRINKER_REGISTERED))) { - if (!shrinker) - clear_bit(i, info->map); + if (unlikely(!shrinker)) { + clear_bit(i, info->map); continue; }
This splits unregister_shrinker() in two parts, and this allows to make the unregistration faster by moving the slow part in delayed asynchronous work. Note, that the guarantees remain the same: no do_shrink_slab() calls are possible after the first part. This will be used in next patch. Signed-off-by: Kirill Tkhai <tkhai@ya.ru> --- include/linux/shrinker.h | 4 ++++ mm/vmscan.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-)