@@ -449,6 +449,21 @@ static struct net *net_alloc(void)
449449 goto out ;
450450}
451451
452+ static LLIST_HEAD (defer_free_list );
453+
454+ static void net_complete_free (void )
455+ {
456+ struct llist_node * kill_list ;
457+ struct net * net , * next ;
458+
459+ /* Get the list of namespaces to free from last round. */
460+ kill_list = llist_del_all (& defer_free_list );
461+
462+ llist_for_each_entry_safe (net , next , kill_list , defer_free_list )
463+ kmem_cache_free (net_cachep , net );
464+
465+ }
466+
452467static void net_free (struct net * net )
453468{
454469 if (refcount_dec_and_test (& net -> passive )) {
@@ -457,7 +472,8 @@ static void net_free(struct net *net)
457472 /* There should not be any trackers left there. */
458473 ref_tracker_dir_exit (& net -> notrefcnt_tracker );
459474
460- kmem_cache_free (net_cachep , net );
475+ /* Wait for an extra rcu_barrier() before final free. */
476+ llist_add (& net -> defer_free_list , & defer_free_list );
461477 }
462478}
463479
@@ -642,6 +658,8 @@ static void cleanup_net(struct work_struct *work)
642658 */
643659 rcu_barrier ();
644660
661+ net_complete_free ();
662+
645663 /* Finally it is safe to free my network namespace structure */
646664 list_for_each_entry_safe (net , tmp , & net_exit_list , exit_list ) {
647665 list_del_init (& net -> exit_list );
0 commit comments