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