@@ -9739,6 +9739,22 @@ static void nft_set_commit_update(struct list_head *set_update_list)
97399739 }
97409740}
97419741
9742+ static unsigned int nft_gc_seq_begin (struct nftables_pernet * nft_net )
9743+ {
9744+ unsigned int gc_seq ;
9745+
9746+ /* Bump gc counter, it becomes odd, this is the busy mark. */
9747+ gc_seq = READ_ONCE (nft_net -> gc_seq );
9748+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9749+
9750+ return gc_seq ;
9751+ }
9752+
9753+ static void nft_gc_seq_end (struct nftables_pernet * nft_net , unsigned int gc_seq )
9754+ {
9755+ WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9756+ }
9757+
97429758static int nf_tables_commit (struct net * net , struct sk_buff * skb )
97439759{
97449760 struct nftables_pernet * nft_net = nft_pernet (net );
@@ -9824,9 +9840,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
98249840
98259841 WRITE_ONCE (nft_net -> base_seq , base_seq );
98269842
9827- /* Bump gc counter, it becomes odd, this is the busy mark. */
9828- gc_seq = READ_ONCE (nft_net -> gc_seq );
9829- WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
9843+ gc_seq = nft_gc_seq_begin (nft_net );
98309844
98319845 /* step 3. Start new generation, rules_gen_X now in use. */
98329846 net -> nft .gencursor = nft_gencursor_next (net );
@@ -10039,7 +10053,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1003910053 nf_tables_gen_notify (net , skb , NFT_MSG_NEWGEN );
1004010054 nf_tables_commit_audit_log (& adl , nft_net -> base_seq );
1004110055
10042- WRITE_ONCE (nft_net -> gc_seq , ++ gc_seq );
10056+ nft_gc_seq_end (nft_net , gc_seq );
1004310057 nf_tables_commit_release (net );
1004410058
1004510059 return 0 ;
@@ -11040,13 +11054,17 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
1104011054 struct net * net = n -> net ;
1104111055 unsigned int deleted ;
1104211056 bool restart = false;
11057+ unsigned int gc_seq ;
1104311058
1104411059 if (event != NETLINK_URELEASE || n -> protocol != NETLINK_NETFILTER )
1104511060 return NOTIFY_DONE ;
1104611061
1104711062 nft_net = nft_pernet (net );
1104811063 deleted = 0 ;
1104911064 mutex_lock (& nft_net -> commit_mutex );
11065+
11066+ gc_seq = nft_gc_seq_begin (nft_net );
11067+
1105011068 if (!list_empty (& nf_tables_destroy_list ))
1105111069 rcu_barrier ();
1105211070again :
@@ -11069,6 +11087,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
1106911087 if (restart )
1107011088 goto again ;
1107111089 }
11090+ nft_gc_seq_end (nft_net , gc_seq );
11091+
1107211092 mutex_unlock (& nft_net -> commit_mutex );
1107311093
1107411094 return NOTIFY_DONE ;
@@ -11106,12 +11126,20 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
1110611126static void __net_exit nf_tables_exit_net (struct net * net )
1110711127{
1110811128 struct nftables_pernet * nft_net = nft_pernet (net );
11129+ unsigned int gc_seq ;
1110911130
1111011131 mutex_lock (& nft_net -> commit_mutex );
11132+
11133+ gc_seq = nft_gc_seq_begin (nft_net );
11134+
1111111135 if (!list_empty (& nft_net -> commit_list ) ||
1111211136 !list_empty (& nft_net -> module_list ))
1111311137 __nf_tables_abort (net , NFNL_ABORT_NONE );
11138+
1111411139 __nft_release_tables (net );
11140+
11141+ nft_gc_seq_end (nft_net , gc_seq );
11142+
1111511143 mutex_unlock (& nft_net -> commit_mutex );
1111611144 WARN_ON_ONCE (!list_empty (& nft_net -> tables ));
1111711145 WARN_ON_ONCE (!list_empty (& nft_net -> module_list ));
0 commit comments