diff --git a/mm/slab_common.c b/mm/slab_common.c index d5a70a831a2a..73f4668d870d 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1954,8 +1954,14 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr) if (!head) might_sleep(); - if (!IS_ENABLED(CONFIG_PREEMPT_RT) && kfree_rcu_sheaf(ptr)) + if (!IS_ENABLED(CONFIG_PREEMPT_RT) && kfree_rcu_sheaf(ptr)) { + /* + * The object is now queued for deferred freeing via an RCU + * sheaf. Tell kmemleak to ignore it. + */ + kmemleak_ignore(ptr); return; + } // Queue the object but don't yet schedule the batch. if (debug_rcu_head_queue(ptr)) { diff --git a/mm/slub.c b/mm/slub.c index 20cb4f3b636d..9e34a9458162 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3014,8 +3014,10 @@ static void pcs_flush_all(struct kmem_cache *s) free_empty_sheaf(s, spare); } - if (rcu_free) + if (rcu_free) { + kmemleak_ignore(rcu_free); call_rcu(&rcu_free->rcu_head, rcu_free_sheaf_nobarn); + } sheaf_flush_main(s); } @@ -3035,6 +3037,7 @@ static void __pcs_flush_all_cpu(struct kmem_cache *s, unsigned int cpu) } if (pcs->rcu_free) { + kmemleak_ignore(pcs->rcu_free); call_rcu(&pcs->rcu_free->rcu_head, rcu_free_sheaf_nobarn); pcs->rcu_free = NULL; } @@ -4031,8 +4034,10 @@ static void flush_rcu_sheaf(struct work_struct *w) local_unlock(&s->cpu_sheaves->lock); - if (rcu_free) + if (rcu_free) { + kmemleak_ignore(rcu_free); call_rcu(&rcu_free->rcu_head, rcu_free_sheaf_nobarn); + } } @@ -5948,8 +5953,15 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj) * we flush before local_unlock to make sure a racing * flush_all_rcu_sheaves() doesn't miss this sheaf */ - if (rcu_sheaf) + if (rcu_sheaf) { + /* + * TODO: Ideally this should be undone in rcu_free_sheaf, + * when the sheaf is returned to a barn to avoid generating + * false negatives. + */ + kmemleak_ignore(rcu_sheaf); call_rcu(&rcu_sheaf->rcu_head, rcu_free_sheaf); + } local_unlock(&s->cpu_sheaves->lock);