@@ -9403,6 +9403,22 @@ static void nft_set_commit_update(struct list_head *set_update_list)
94039403 }
94049404}
94059405
9406+ static unsigned int nft_gc_seq_begin (struct nftables_pernet * nft_net )
9407+ {
9408+ unsigned int gc_seq ;
9409+
9410+ /* Bump gc counter, it becomes odd, this is the busy mark. */
9411+ gc_seq = READ_ONCE (nft_net -> gc_seq );
9412+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9413+
9414+ return gc_seq ;
9415+ }
9416+
9417+ static void nft_gc_seq_end (struct nftables_pernet * nft_net , unsigned int gc_seq )
9418+ {
9419+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9420+ }
9421+
94069422static int nf_tables_commit (struct net * net , struct sk_buff * skb )
94079423{
94089424 struct nftables_pernet * nft_net = nft_pernet (net );
@@ -9488,9 +9504,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
94889504
94899505 WRITE_ONCE (nft_net -> base_seq , base_seq );
94909506
9491- /* Bump gc counter, it becomes odd, this is the busy mark. */
9492- gc_seq = READ_ONCE (nft_net -> gc_seq );
9493- WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9507+ gc_seq = nft_gc_seq_begin (nft_net );
94949508
94959509 /* step 3. Start new generation, rules_gen_X now in use. */
94969510 net -> nft .gencursor = nft_gencursor_next (net );
@@ -9688,7 +9702,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
96889702 nf_tables_gen_notify (net , skb , NFT_MSG_NEWGEN );
96899703 nf_tables_commit_audit_log (& adl , nft_net -> base_seq );
96909704
9691- WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9705+ nft_gc_seq_end (nft_net , gc_seq );
96929706 nf_tables_commit_release (net );
96939707
96949708 return 0 ;
@@ -10678,13 +10692,17 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
1067810692 struct net * net = n -> net ;
1067910693 unsigned int deleted ;
1068010694 bool restart = false;
10695+ unsigned int gc_seq ;
1068110696
1068210697 if (event != NETLINK_URELEASE || n -> protocol != NETLINK_NETFILTER )
1068310698 return NOTIFY_DONE ;
1068410699
1068510700 nft_net = nft_pernet (net );
1068610701 deleted = 0 ;
1068710702 mutex_lock (& nft_net -> commit_mutex );
10703+
10704+ gc_seq = nft_gc_seq_begin (nft_net );
10705+
1068810706 if (!list_empty (& nf_tables_destroy_list ))
1068910707 rcu_barrier ();
1069010708again :
@@ -10707,6 +10725,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
1070710725 if (restart )
1070810726 goto again ;
1070910727 }
10728+ nft_gc_seq_end (nft_net , gc_seq );
10729+
1071010730 mutex_unlock (& nft_net -> commit_mutex );
1071110731
1071210732 return NOTIFY_DONE ;
@@ -10745,12 +10765,20 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
1074510765static void __net_exit nf_tables_exit_net (struct net * net )
1074610766{
1074710767 struct nftables_pernet * nft_net = nft_pernet (net );
10768+ unsigned int gc_seq ;
1074810769
1074910770 mutex_lock (& nft_net -> commit_mutex );
10771+
10772+ gc_seq = nft_gc_seq_begin (nft_net );
10773+
1075010774 if (!list_empty (& nft_net -> commit_list ) ||
1075110775 !list_empty (& nft_net -> module_list ))
1075210776 __nf_tables_abort (net , NFNL_ABORT_NONE );
10777+
1075310778 __nft_release_tables (net );
10779+
10780+ nft_gc_seq_end (nft_net , gc_seq );
10781+
1075410782 mutex_unlock (& nft_net -> commit_mutex );
1075510783 WARN_ON_ONCE (!list_empty (& nft_net -> tables ));
1075610784 WARN_ON_ONCE (!list_empty (& nft_net -> module_list ));
0 commit comments