@@ -581,6 +581,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
581581 return __nft_trans_set_add (ctx , msg_type , set , NULL );
582582}
583583
584+ static void nft_setelem_data_deactivate (const struct net * net ,
585+ const struct nft_set * set ,
586+ struct nft_set_elem * elem );
587+
588+ static int nft_mapelem_deactivate (const struct nft_ctx * ctx ,
589+ struct nft_set * set ,
590+ const struct nft_set_iter * iter ,
591+ struct nft_set_elem * elem )
592+ {
593+ nft_setelem_data_deactivate (ctx -> net , set , elem );
594+
595+ return 0 ;
596+ }
597+
598+ struct nft_set_elem_catchall {
599+ struct list_head list ;
600+ struct rcu_head rcu ;
601+ void * elem ;
602+ };
603+
604+ static void nft_map_catchall_deactivate (const struct nft_ctx * ctx ,
605+ struct nft_set * set )
606+ {
607+ u8 genmask = nft_genmask_next (ctx -> net );
608+ struct nft_set_elem_catchall * catchall ;
609+ struct nft_set_elem elem ;
610+ struct nft_set_ext * ext ;
611+
612+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
613+ ext = nft_set_elem_ext (set , catchall -> elem );
614+ if (!nft_set_elem_active (ext , genmask ))
615+ continue ;
616+
617+ elem .priv = catchall -> elem ;
618+ nft_setelem_data_deactivate (ctx -> net , set , & elem );
619+ break ;
620+ }
621+ }
622+
623+ static void nft_map_deactivate (const struct nft_ctx * ctx , struct nft_set * set )
624+ {
625+ struct nft_set_iter iter = {
626+ .genmask = nft_genmask_next (ctx -> net ),
627+ .fn = nft_mapelem_deactivate ,
628+ };
629+
630+ set -> ops -> walk (ctx , set , & iter );
631+ WARN_ON_ONCE (iter .err );
632+
633+ nft_map_catchall_deactivate (ctx , set );
634+ }
635+
584636static int nft_delset (const struct nft_ctx * ctx , struct nft_set * set )
585637{
586638 int err ;
@@ -589,6 +641,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
589641 if (err < 0 )
590642 return err ;
591643
644+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
645+ nft_map_deactivate (ctx , set );
646+
592647 nft_deactivate_next (ctx -> net , set );
593648 ctx -> table -> use -- ;
594649
@@ -3408,12 +3463,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
34083463 return 0 ;
34093464}
34103465
3411- struct nft_set_elem_catchall {
3412- struct list_head list ;
3413- struct rcu_head rcu ;
3414- void * elem ;
3415- };
3416-
34173466int nft_set_catchall_validate (const struct nft_ctx * ctx , struct nft_set * set )
34183467{
34193468 u8 genmask = nft_genmask_next (ctx -> net );
@@ -4739,7 +4788,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
47394788 for (i = 0 ; i < set -> num_exprs ; i ++ )
47404789 nft_expr_destroy (& ctx , set -> exprs [i ]);
47414790err_set_destroy :
4742- ops -> destroy (set );
4791+ ops -> destroy (& ctx , set );
47434792err_set_init :
47444793 kfree (set -> name );
47454794err_set_name :
@@ -4754,7 +4803,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
47544803
47554804 list_for_each_entry_safe (catchall , next , & set -> catchall_list , list ) {
47564805 list_del_rcu (& catchall -> list );
4757- nft_set_elem_destroy ( set , catchall -> elem , true );
4806+ nf_tables_set_elem_destroy ( ctx , set , catchall -> elem );
47584807 kfree_rcu (catchall , rcu );
47594808 }
47604809}
@@ -4769,7 +4818,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
47694818 for (i = 0 ; i < set -> num_exprs ; i ++ )
47704819 nft_expr_destroy (ctx , set -> exprs [i ]);
47714820
4772- set -> ops -> destroy (set );
4821+ set -> ops -> destroy (ctx , set );
47734822 nft_set_catchall_destroy (ctx , set );
47744823 kfree (set -> name );
47754824 kvfree (set );
@@ -4930,10 +4979,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
49304979 }
49314980}
49324981
4982+ static void nft_setelem_data_activate (const struct net * net ,
4983+ const struct nft_set * set ,
4984+ struct nft_set_elem * elem );
4985+
4986+ static int nft_mapelem_activate (const struct nft_ctx * ctx ,
4987+ struct nft_set * set ,
4988+ const struct nft_set_iter * iter ,
4989+ struct nft_set_elem * elem )
4990+ {
4991+ nft_setelem_data_activate (ctx -> net , set , elem );
4992+
4993+ return 0 ;
4994+ }
4995+
4996+ static void nft_map_catchall_activate (const struct nft_ctx * ctx ,
4997+ struct nft_set * set )
4998+ {
4999+ u8 genmask = nft_genmask_next (ctx -> net );
5000+ struct nft_set_elem_catchall * catchall ;
5001+ struct nft_set_elem elem ;
5002+ struct nft_set_ext * ext ;
5003+
5004+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
5005+ ext = nft_set_elem_ext (set , catchall -> elem );
5006+ if (!nft_set_elem_active (ext , genmask ))
5007+ continue ;
5008+
5009+ elem .priv = catchall -> elem ;
5010+ nft_setelem_data_activate (ctx -> net , set , & elem );
5011+ break ;
5012+ }
5013+ }
5014+
5015+ static void nft_map_activate (const struct nft_ctx * ctx , struct nft_set * set )
5016+ {
5017+ struct nft_set_iter iter = {
5018+ .genmask = nft_genmask_next (ctx -> net ),
5019+ .fn = nft_mapelem_activate ,
5020+ };
5021+
5022+ set -> ops -> walk (ctx , set , & iter );
5023+ WARN_ON_ONCE (iter .err );
5024+
5025+ nft_map_catchall_activate (ctx , set );
5026+ }
5027+
49335028void nf_tables_activate_set (const struct nft_ctx * ctx , struct nft_set * set )
49345029{
4935- if (nft_set_is_anonymous (set ))
5030+ if (nft_set_is_anonymous (set )) {
5031+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5032+ nft_map_activate (ctx , set );
5033+
49365034 nft_clear (ctx -> net , set );
5035+ }
49375036
49385037 set -> use ++ ;
49395038}
@@ -4954,13 +5053,20 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
49545053 set -> use -- ;
49555054 break ;
49565055 case NFT_TRANS_PREPARE :
4957- if (nft_set_is_anonymous (set ))
4958- nft_deactivate_next (ctx -> net , set );
5056+ if (nft_set_is_anonymous (set )) {
5057+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5058+ nft_map_deactivate (ctx , set );
49595059
5060+ nft_deactivate_next (ctx -> net , set );
5061+ }
49605062 set -> use -- ;
49615063 return ;
49625064 case NFT_TRANS_ABORT :
49635065 case NFT_TRANS_RELEASE :
5066+ if (nft_set_is_anonymous (set ) &&
5067+ set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5068+ nft_map_deactivate (ctx , set );
5069+
49645070 set -> use -- ;
49655071 fallthrough ;
49665072 default :
@@ -5676,6 +5782,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
56765782 __nft_set_elem_expr_destroy (ctx , expr );
56775783}
56785784
5785+ /* Drop references and destroy. Called from gc, dynset and abort path. */
56795786void nft_set_elem_destroy (const struct nft_set * set , void * elem ,
56805787 bool destroy_expr )
56815788{
@@ -5697,11 +5804,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
56975804}
56985805EXPORT_SYMBOL_GPL (nft_set_elem_destroy );
56995806
5700- /* Only called from commit path, nft_setelem_data_deactivate() already deals
5701- * with the refcounting from the preparation phase .
5807+ /* Destroy element. References have been already dropped in the preparation
5808+ * path via nft_setelem_data_deactivate() .
57025809 */
5703- static void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
5704- const struct nft_set * set , void * elem )
5810+ void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
5811+ const struct nft_set * set , void * elem )
57055812{
57065813 struct nft_set_ext * ext = nft_set_elem_ext (set , elem );
57075814
@@ -9330,6 +9437,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
93309437 case NFT_MSG_DELSET :
93319438 trans -> ctx .table -> use ++ ;
93329439 nft_clear (trans -> ctx .net , nft_trans_set (trans ));
9440+ if (nft_trans_set (trans )-> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
9441+ nft_map_activate (& trans -> ctx , nft_trans_set (trans ));
9442+
93339443 nft_trans_destroy (trans );
93349444 break ;
93359445 case NFT_MSG_NEWSETELEM :
@@ -10097,6 +10207,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
1009710207 list_for_each_entry_safe (set , ns , & table -> sets , list ) {
1009810208 list_del (& set -> list );
1009910209 table -> use -- ;
10210+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
10211+ nft_map_deactivate (& ctx , set );
10212+
1010010213 nft_set_destroy (& ctx , set );
1010110214 }
1010210215 list_for_each_entry_safe (obj , ne , & table -> objects , list ) {
0 commit comments