@@ -559,6 +559,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
559559 return __nft_trans_set_add (ctx , msg_type , set , NULL );
560560}
561561
562+ static void nft_setelem_data_deactivate (const struct net * net ,
563+ const struct nft_set * set ,
564+ struct nft_set_elem * elem );
565+
566+ static int nft_mapelem_deactivate (const struct nft_ctx * ctx ,
567+ struct nft_set * set ,
568+ const struct nft_set_iter * iter ,
569+ struct nft_set_elem * elem )
570+ {
571+ nft_setelem_data_deactivate (ctx -> net , set , elem );
572+
573+ return 0 ;
574+ }
575+
576+ struct nft_set_elem_catchall {
577+ struct list_head list ;
578+ struct rcu_head rcu ;
579+ void * elem ;
580+ };
581+
582+ static void nft_map_catchall_deactivate (const struct nft_ctx * ctx ,
583+ struct nft_set * set )
584+ {
585+ u8 genmask = nft_genmask_next (ctx -> net );
586+ struct nft_set_elem_catchall * catchall ;
587+ struct nft_set_elem elem ;
588+ struct nft_set_ext * ext ;
589+
590+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
591+ ext = nft_set_elem_ext (set , catchall -> elem );
592+ if (!nft_set_elem_active (ext , genmask ))
593+ continue ;
594+
595+ elem .priv = catchall -> elem ;
596+ nft_setelem_data_deactivate (ctx -> net , set , & elem );
597+ break ;
598+ }
599+ }
600+
601+ static void nft_map_deactivate (const struct nft_ctx * ctx , struct nft_set * set )
602+ {
603+ struct nft_set_iter iter = {
604+ .genmask = nft_genmask_next (ctx -> net ),
605+ .fn = nft_mapelem_deactivate ,
606+ };
607+
608+ set -> ops -> walk (ctx , set , & iter );
609+ WARN_ON_ONCE (iter .err );
610+
611+ nft_map_catchall_deactivate (ctx , set );
612+ }
613+
562614static int nft_delset (const struct nft_ctx * ctx , struct nft_set * set )
563615{
564616 int err ;
@@ -567,6 +619,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
567619 if (err < 0 )
568620 return err ;
569621
622+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
623+ nft_map_deactivate (ctx , set );
624+
570625 nft_deactivate_next (ctx -> net , set );
571626 ctx -> table -> use -- ;
572627
@@ -3659,12 +3714,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
36593714 return 0 ;
36603715}
36613716
3662- struct nft_set_elem_catchall {
3663- struct list_head list ;
3664- struct rcu_head rcu ;
3665- void * elem ;
3666- };
3667-
36683717int nft_set_catchall_validate (const struct nft_ctx * ctx , struct nft_set * set )
36693718{
36703719 u8 genmask = nft_genmask_next (ctx -> net );
@@ -4997,7 +5046,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
49975046 for (i = 0 ; i < set -> num_exprs ; i ++ )
49985047 nft_expr_destroy (& ctx , set -> exprs [i ]);
49995048err_set_destroy :
5000- ops -> destroy (set );
5049+ ops -> destroy (& ctx , set );
50015050err_set_init :
50025051 kfree (set -> name );
50035052err_set_name :
@@ -5012,7 +5061,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
50125061
50135062 list_for_each_entry_safe (catchall , next , & set -> catchall_list , list ) {
50145063 list_del_rcu (& catchall -> list );
5015- nft_set_elem_destroy ( set , catchall -> elem , true );
5064+ nf_tables_set_elem_destroy ( ctx , set , catchall -> elem );
50165065 kfree_rcu (catchall , rcu );
50175066 }
50185067}
@@ -5027,7 +5076,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
50275076 for (i = 0 ; i < set -> num_exprs ; i ++ )
50285077 nft_expr_destroy (ctx , set -> exprs [i ]);
50295078
5030- set -> ops -> destroy (set );
5079+ set -> ops -> destroy (ctx , set );
50315080 nft_set_catchall_destroy (ctx , set );
50325081 kfree (set -> name );
50335082 kvfree (set );
@@ -5192,10 +5241,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
51925241 }
51935242}
51945243
5244+ static void nft_setelem_data_activate (const struct net * net ,
5245+ const struct nft_set * set ,
5246+ struct nft_set_elem * elem );
5247+
5248+ static int nft_mapelem_activate (const struct nft_ctx * ctx ,
5249+ struct nft_set * set ,
5250+ const struct nft_set_iter * iter ,
5251+ struct nft_set_elem * elem )
5252+ {
5253+ nft_setelem_data_activate (ctx -> net , set , elem );
5254+
5255+ return 0 ;
5256+ }
5257+
5258+ static void nft_map_catchall_activate (const struct nft_ctx * ctx ,
5259+ struct nft_set * set )
5260+ {
5261+ u8 genmask = nft_genmask_next (ctx -> net );
5262+ struct nft_set_elem_catchall * catchall ;
5263+ struct nft_set_elem elem ;
5264+ struct nft_set_ext * ext ;
5265+
5266+ list_for_each_entry (catchall , & set -> catchall_list , list ) {
5267+ ext = nft_set_elem_ext (set , catchall -> elem );
5268+ if (!nft_set_elem_active (ext , genmask ))
5269+ continue ;
5270+
5271+ elem .priv = catchall -> elem ;
5272+ nft_setelem_data_activate (ctx -> net , set , & elem );
5273+ break ;
5274+ }
5275+ }
5276+
5277+ static void nft_map_activate (const struct nft_ctx * ctx , struct nft_set * set )
5278+ {
5279+ struct nft_set_iter iter = {
5280+ .genmask = nft_genmask_next (ctx -> net ),
5281+ .fn = nft_mapelem_activate ,
5282+ };
5283+
5284+ set -> ops -> walk (ctx , set , & iter );
5285+ WARN_ON_ONCE (iter .err );
5286+
5287+ nft_map_catchall_activate (ctx , set );
5288+ }
5289+
51955290void nf_tables_activate_set (const struct nft_ctx * ctx , struct nft_set * set )
51965291{
5197- if (nft_set_is_anonymous (set ))
5292+ if (nft_set_is_anonymous (set )) {
5293+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5294+ nft_map_activate (ctx , set );
5295+
51985296 nft_clear (ctx -> net , set );
5297+ }
51995298
52005299 set -> use ++ ;
52015300}
@@ -5214,13 +5313,20 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
52145313 set -> use -- ;
52155314 break ;
52165315 case NFT_TRANS_PREPARE :
5217- if (nft_set_is_anonymous (set ))
5218- nft_deactivate_next (ctx -> net , set );
5316+ if (nft_set_is_anonymous (set )) {
5317+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5318+ nft_map_deactivate (ctx , set );
52195319
5320+ nft_deactivate_next (ctx -> net , set );
5321+ }
52205322 set -> use -- ;
52215323 return ;
52225324 case NFT_TRANS_ABORT :
52235325 case NFT_TRANS_RELEASE :
5326+ if (nft_set_is_anonymous (set ) &&
5327+ set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
5328+ nft_map_deactivate (ctx , set );
5329+
52245330 set -> use -- ;
52255331 fallthrough ;
52265332 default :
@@ -5973,6 +6079,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
59736079 __nft_set_elem_expr_destroy (ctx , expr );
59746080}
59756081
6082+ /* Drop references and destroy. Called from gc, dynset and abort path. */
59766083void nft_set_elem_destroy (const struct nft_set * set , void * elem ,
59776084 bool destroy_expr )
59786085{
@@ -5994,11 +6101,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
59946101}
59956102EXPORT_SYMBOL_GPL (nft_set_elem_destroy );
59966103
5997- /* Only called from commit path, nft_setelem_data_deactivate() already deals
5998- * with the refcounting from the preparation phase .
6104+ /* Destroy element. References have been already dropped in the preparation
6105+ * path via nft_setelem_data_deactivate() .
59996106 */
6000- static void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
6001- const struct nft_set * set , void * elem )
6107+ void nf_tables_set_elem_destroy (const struct nft_ctx * ctx ,
6108+ const struct nft_set * set , void * elem )
60026109{
60036110 struct nft_set_ext * ext = nft_set_elem_ext (set , elem );
60046111
@@ -6631,7 +6738,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
66316738 if (obj )
66326739 obj -> use -- ;
66336740err_elem_userdata :
6634- nf_tables_set_elem_destroy ( ctx , set , elem .priv );
6741+ nft_set_elem_destroy ( set , elem .priv , true );
66356742err_parse_data :
66366743 if (nla [NFTA_SET_ELEM_DATA ] != NULL )
66376744 nft_data_release (& elem .data .val , desc .type );
@@ -9799,6 +9906,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
97999906 case NFT_MSG_DESTROYSET :
98009907 trans -> ctx .table -> use ++ ;
98019908 nft_clear (trans -> ctx .net , nft_trans_set (trans ));
9909+ if (nft_trans_set (trans )-> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
9910+ nft_map_activate (& trans -> ctx , nft_trans_set (trans ));
9911+
98029912 nft_trans_destroy (trans );
98039913 break ;
98049914 case NFT_MSG_NEWSETELEM :
@@ -10568,6 +10678,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
1056810678 list_for_each_entry_safe (set , ns , & table -> sets , list ) {
1056910679 list_del (& set -> list );
1057010680 table -> use -- ;
10681+ if (set -> flags & (NFT_SET_MAP | NFT_SET_OBJECT ))
10682+ nft_map_deactivate (& ctx , set );
10683+
1057110684 nft_set_destroy (& ctx , set );
1057210685 }
1057310686 list_for_each_entry_safe (obj , ne , & table -> objects , list ) {
0 commit comments