Message ID | 20221116141511.3695680-1-qiang1.zhang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | rcu: Make vmalloc_dump_obj() call in a preemptible context | expand |
On 2022/11/16 22:15, Zqiang wrote: > Currently, the mem_dump_obj() is invoked in call_rcu(), the Plan to call mem_dump_obj() in rcu_do_batch(). > call_rcu() is maybe invoked in non-preemptive code segment, > for object allocated from vmalloc(), the following scenarios > may occur: > > CPU 0 > tasks context > spin_lock(&vmap_area_lock) > Interrupt context > call_rcu() > mem_dump_obj > vmalloc_dump_obj > spin_lock(&vmap_area_lock) <--deadlock > > and for PREEMPT-RT kernel, the spinlock will convert to sleepable > lock, it also make vmap_area_lock spinlock can not acquire in > non-preemptive code segment. therefore, this commit make the > vmalloc_dump_obj() call in a preemptible context. > > Signed-off-by: Zqiang <qiang1.zhang@intel.com> > --- > mm/util.c | 10 +++++++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/mm/util.c b/mm/util.c > index 12984e76767e..465f8b8824ca 100644 > --- a/mm/util.c > +++ b/mm/util.c > @@ -1124,8 +1124,12 @@ void mem_dump_obj(void *object) > return; > } > > - if (vmalloc_dump_obj(object)) > - return; > + if (is_vmalloc_addr(object)) { > + if (preemptible() && vmalloc_dump_obj(object)) preemptible() --> !in_interrupt()? > + return; > + type = "vmalloc memory"; > + goto end; > + } Move into vmalloc_dump_obj()? > > if (virt_addr_valid(object)) > type = "non-slab/vmalloc memory"; > @@ -1135,7 +1139,7 @@ void mem_dump_obj(void *object) > type = "zero-size pointer"; > else > type = "non-paged memory"; > - > +end: > pr_cont(" %s\n", type); > } > EXPORT_SYMBOL_GPL(mem_dump_obj); >
On 2022/11/16 22:15, Zqiang wrote: > Currently, the mem_dump_obj() is invoked in call_rcu(), the > >Plan to call mem_dump_obj() in rcu_do_batch(). > > call_rcu() is maybe invoked in non-preemptive code segment, > for object allocated from vmalloc(), the following scenarios > may occur: > > CPU 0 > tasks context > spin_lock(&vmap_area_lock) > Interrupt context > call_rcu() > mem_dump_obj > vmalloc_dump_obj > spin_lock(&vmap_area_lock) <--deadlock > > and for PREEMPT-RT kernel, the spinlock will convert to sleepable > lock, it also make vmap_area_lock spinlock can not acquire in > non-preemptive code segment. therefore, this commit make the > vmalloc_dump_obj() call in a preemptible context. > > Signed-off-by: Zqiang <qiang1.zhang@intel.com> > --- > mm/util.c | 10 +++++++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/mm/util.c b/mm/util.c > index 12984e76767e..465f8b8824ca 100644 > --- a/mm/util.c > +++ b/mm/util.c > @@ -1124,8 +1124,12 @@ void mem_dump_obj(void *object) > return; > } > > - if (vmalloc_dump_obj(object)) > - return; > + if (is_vmalloc_addr(object)) { > + if (preemptible() && vmalloc_dump_obj(object)) > >preemptible() --> !in_interrupt()? Hi Leizhen !in_interrupt() not include following scenario: task context: local_irq_save() or preempt_disable(); call_rcu() mem_dump_obj() vmalloc_dump_obj() spin_lock(&vmap_area_lock) local_irq_restore() or preempt_denable(); for PREEMPT-RT kernel, spinlock will convert to sleepable lock. > > + return; > + type = "vmalloc memory"; > + goto end; > + } > >Move into vmalloc_dump_obj()? you mean move preemptible() into vmalloc_dump_obj()? Thanks Zqiang > > > if (virt_addr_valid(object)) > type = "non-slab/vmalloc memory"; > @@ -1135,7 +1139,7 @@ void mem_dump_obj(void *object) > type = "zero-size pointer"; > else > type = "non-paged memory"; > - > +end: > pr_cont(" %s\n", type); > } > EXPORT_SYMBOL_GPL(mem_dump_obj); >
On 2022/11/17 13:20, Zhang, Qiang1 wrote: > > > On 2022/11/16 22:15, Zqiang wrote: >> Currently, the mem_dump_obj() is invoked in call_rcu(), the >> >> Plan to call mem_dump_obj() in rcu_do_batch(). >> >> call_rcu() is maybe invoked in non-preemptive code segment, >> for object allocated from vmalloc(), the following scenarios >> may occur: >> >> CPU 0 >> tasks context >> spin_lock(&vmap_area_lock) >> Interrupt context >> call_rcu() >> mem_dump_obj >> vmalloc_dump_obj >> spin_lock(&vmap_area_lock) <--deadlock >> >> and for PREEMPT-RT kernel, the spinlock will convert to sleepable >> lock, it also make vmap_area_lock spinlock can not acquire in >> non-preemptive code segment. therefore, this commit make the >> vmalloc_dump_obj() call in a preemptible context. >> >> Signed-off-by: Zqiang <qiang1.zhang@intel.com> >> --- >> mm/util.c | 10 +++++++--- >> 1 file changed, 7 insertions(+), 3 deletions(-) >> >> diff --git a/mm/util.c b/mm/util.c >> index 12984e76767e..465f8b8824ca 100644 >> --- a/mm/util.c >> +++ b/mm/util.c >> @@ -1124,8 +1124,12 @@ void mem_dump_obj(void *object) >> return; >> } >> >> - if (vmalloc_dump_obj(object)) >> - return; >> + if (is_vmalloc_addr(object)) { >> + if (preemptible() && vmalloc_dump_obj(object)) >> >> preemptible() --> !in_interrupt()? > > Hi Leizhen > > !in_interrupt() not include following scenario: > > task context: > > local_irq_save() or preempt_disable(); > call_rcu() > mem_dump_obj() > vmalloc_dump_obj() > spin_lock(&vmap_area_lock) > local_irq_restore() or preempt_denable(); > > for PREEMPT-RT kernel, spinlock will convert to sleepable lock. OK. > >> >> + return; >> + type = "vmalloc memory"; >> + goto end; >> + } >> >> Move into vmalloc_dump_obj()? > > you mean move preemptible() into vmalloc_dump_obj()? Move all? Currently, vmalloc_dump_obj() is invoked only by mem_dump_obj(). The encapsulation is a little better in my opinion. > > Thanks > Zqiang > >> >> >> if (virt_addr_valid(object)) >> type = "non-slab/vmalloc memory"; >> @@ -1135,7 +1139,7 @@ void mem_dump_obj(void *object) >> type = "zero-size pointer"; >> else >> type = "non-paged memory"; >> - >> +end: >> pr_cont(" %s\n", type); >> } >> EXPORT_SYMBOL_GPL(mem_dump_obj); >> >
diff --git a/mm/util.c b/mm/util.c index 12984e76767e..465f8b8824ca 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1124,8 +1124,12 @@ void mem_dump_obj(void *object) return; } - if (vmalloc_dump_obj(object)) - return; + if (is_vmalloc_addr(object)) { + if (preemptible() && vmalloc_dump_obj(object)) + return; + type = "vmalloc memory"; + goto end; + } if (virt_addr_valid(object)) type = "non-slab/vmalloc memory"; @@ -1135,7 +1139,7 @@ void mem_dump_obj(void *object) type = "zero-size pointer"; else type = "non-paged memory"; - +end: pr_cont(" %s\n", type); } EXPORT_SYMBOL_GPL(mem_dump_obj);
Currently, the mem_dump_obj() is invoked in call_rcu(), the call_rcu() is maybe invoked in non-preemptive code segment, for object allocated from vmalloc(), the following scenarios may occur: CPU 0 tasks context spin_lock(&vmap_area_lock) Interrupt context call_rcu() mem_dump_obj vmalloc_dump_obj spin_lock(&vmap_area_lock) <--deadlock and for PREEMPT-RT kernel, the spinlock will convert to sleepable lock, it also make vmap_area_lock spinlock can not acquire in non-preemptive code segment. therefore, this commit make the vmalloc_dump_obj() call in a preemptible context. Signed-off-by: Zqiang <qiang1.zhang@intel.com> --- mm/util.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)