@@ -449,6 +449,21 @@ static struct net *net_alloc(void)
449
449
goto out ;
450
450
}
451
451
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
+
452
467
static void net_free (struct net * net )
453
468
{
454
469
if (refcount_dec_and_test (& net -> passive )) {
@@ -457,7 +472,8 @@ static void net_free(struct net *net)
457
472
/* There should not be any trackers left there. */
458
473
ref_tracker_dir_exit (& net -> notrefcnt_tracker );
459
474
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 );
461
477
}
462
478
}
463
479
@@ -642,6 +658,8 @@ static void cleanup_net(struct work_struct *work)
642
658
*/
643
659
rcu_barrier ();
644
660
661
+ net_complete_free ();
662
+
645
663
/* Finally it is safe to free my network namespace structure */
646
664
list_for_each_entry_safe (net , tmp , & net_exit_list , exit_list ) {
647
665
list_del_init (& net -> exit_list );
0 commit comments