@@ -446,6 +446,21 @@ static struct net *net_alloc(void)
446
446
goto out ;
447
447
}
448
448
449
+ static LLIST_HEAD (defer_free_list );
450
+
451
+ static void net_complete_free (void )
452
+ {
453
+ struct llist_node * kill_list ;
454
+ struct net * net , * next ;
455
+
456
+ /* Get the list of namespaces to free from last round. */
457
+ kill_list = llist_del_all (& defer_free_list );
458
+
459
+ llist_for_each_entry_safe (net , next , kill_list , defer_free_list )
460
+ kmem_cache_free (net_cachep , net );
461
+
462
+ }
463
+
449
464
static void net_free (struct net * net )
450
465
{
451
466
if (refcount_dec_and_test (& net -> passive )) {
@@ -454,7 +469,8 @@ static void net_free(struct net *net)
454
469
/* There should not be any trackers left there. */
455
470
ref_tracker_dir_exit (& net -> notrefcnt_tracker );
456
471
457
- kmem_cache_free (net_cachep , net );
472
+ /* Wait for an extra rcu_barrier() before final free. */
473
+ llist_add (& net -> defer_free_list , & defer_free_list );
458
474
}
459
475
}
460
476
@@ -631,6 +647,8 @@ static void cleanup_net(struct work_struct *work)
631
647
*/
632
648
rcu_barrier ();
633
649
650
+ net_complete_free ();
651
+
634
652
/* Finally it is safe to free my network namespace structure */
635
653
list_for_each_entry_safe (net , tmp , & net_exit_list , exit_list ) {
636
654
list_del_init (& net -> exit_list );
0 commit comments