--- x/include/linux/mm_types.h +++ y/include/linux/mm_types.h @@ -1166,6 +1166,7 @@ struct mm_struct { #ifdef CONFIG_PREEMPT_RT struct rcu_head delayed_drop; #endif + struct work_struct drop_work; #ifdef CONFIG_HUGETLB_PAGE atomic_long_t hugetlb_usage; #endif --- x/kernel/fork.c +++ y/kernel/fork.c @@ -666,6 +666,14 @@ static void cleanup_lazy_tlbs(struct mm_ on_each_cpu(do_check_lazy_tlb, (void *)mm, 1); } +static void mmdrop_workfn(struct work_struct *work) +{ + struct mm_struct *mm; + + mm = container_of(work, struct mm_struct, drop_work); + futex_hash_free(mm); + free_mm(mm); +} /* * Called when the last reference to the mm * is dropped: either by a lazy thread or by @@ -689,9 +697,8 @@ void __mmdrop(struct mm_struct *mm) mm_pasid_drop(mm); mm_destroy_cid(mm); percpu_counter_destroy_many(mm->rss_stat, NR_MM_COUNTERS); - futex_hash_free(mm); - - free_mm(mm); + INIT_WORK(&mm->drop_work, mmdrop_workfn); + schedule_work(&mm->drop_work); } EXPORT_SYMBOL_GPL(__mmdrop);