On Thu, Aug 17, 2023 at 2:34 AM Zqiang <qiang.zhang1211@xxxxxxxxx> wrote: > > Currently, for double invoke call_rcu(), will dump rcu_head objects > memory info, if the objects is not allocated from the slab allocator, > the vmalloc_dump_obj() will be invoke and the vmap_area_lock spinlock > need to be held, since the call_rcu() can be invoked in interrupt context, > therefore, there is a possibility of spinlock deadlock scenarios. > > And in Preempt-RT kernel, the rcutorture test also trigger the following > lockdep warning: > > BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48 > in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 1, name: swapper/0 [...] > > The statistics about the source of 'rhp', the kmem_valid_obj() accounts > for more than 97.5%, and vmalloc accounts for less than 1%, this statistic > comes from leizhen. this commit therefore drop vmalloc_dump_obj() from > mem_dump_obj() and only check whether is vmalloc address. > Signed-off-by: Zqiang <qiang.zhang1211@xxxxxxxxx> > --- > include/linux/vmalloc.h | 5 ----- > mm/util.c | 7 +++---- > mm/vmalloc.c | 14 -------------- > 3 files changed, 3 insertions(+), 23 deletions(-) > > diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h > index c720be70c8dd..d7c4e112a4ad 100644 > --- a/include/linux/vmalloc.h > +++ b/include/linux/vmalloc.h > @@ -289,10 +289,5 @@ pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms) > int register_vmap_purge_notifier(struct notifier_block *nb); > int unregister_vmap_purge_notifier(struct notifier_block *nb); > > -#if defined(CONFIG_MMU) && defined(CONFIG_PRINTK) > -bool vmalloc_dump_obj(void *object); > -#else > -static inline bool vmalloc_dump_obj(void *object) { return false; } > -#endif > > #endif /* _LINUX_VMALLOC_H */ > diff --git a/mm/util.c b/mm/util.c > index ddfbb22dc187..fbc007adc108 100644 > --- a/mm/util.c > +++ b/mm/util.c > @@ -1066,10 +1066,9 @@ void mem_dump_obj(void *object) > if (kmem_dump_obj(object)) > return; > > - if (vmalloc_dump_obj(object)) > - return; > - > - if (virt_addr_valid(object)) > + if (is_vmalloc_addr(object)) > + type = "vmalloc memory"; > + else if (virt_addr_valid(object)) > type = "non-slab/vmalloc memory"; > else if (object == NULL) > type = "NULL pointer"; > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > index 93cf99aba335..224af955bcb5 100644 > --- a/mm/vmalloc.c > +++ b/mm/vmalloc.c > @@ -4271,20 +4271,6 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms) > } > #endif /* CONFIG_SMP */ > > -#ifdef CONFIG_PRINTK > -bool vmalloc_dump_obj(void *object) > -{ > - struct vm_struct *vm; > - void *objp = (void *)PAGE_ALIGN((unsigned long)object); > - > - vm = find_vm_area(objp); What about adding something like the following to vmalloc.c. Would it work? +static struct vmap_area *find_vmap_area_trylock(unsigned long addr) +{ + struct vmap_area *va; + + if (!spin_trylock(&vmap_area_lock)) + return NULL; + va = __find_vmap_area(addr); + spin_unlock(&vmap_area_lock); + + return va; +} and call it from vmalloc_dump_obj(): vm = find_vm_area_trylock(objp); And then keep the rest of your patch as it is but add back the call to vmalloc_dump_obj() in mem_dump_obj(): if (vmalloc_dump_obj(object)) return; - if (virt_addr_valid(object)) + if (is_vmalloc_addr(object)) + type = "vmalloc memory"; + else if (virt_addr_valid(object)) type = "non-slab/vmalloc memory"; If that still throws "sleeping function called" type warnings, then that is a preempt RT issue because spin_trylock() on conversion to a sleeping lock should not be sleeping as it is uncontended. But I could be missing something and I'll look more later. But for now off to pick up a rental car here... thanks, - Joel