@@ -158,7 +158,7 @@ static int __tcf_action_put(struct tc_action *p, bool bind)
158
158
return 0 ;
159
159
}
160
160
161
- int __tcf_idr_release (struct tc_action * p , bool bind , bool strict )
161
+ static int __tcf_idr_release (struct tc_action * p , bool bind , bool strict )
162
162
{
163
163
int ret = 0 ;
164
164
@@ -184,7 +184,18 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
184
184
185
185
return ret ;
186
186
}
187
- EXPORT_SYMBOL (__tcf_idr_release );
187
+
188
+ int tcf_idr_release (struct tc_action * a , bool bind )
189
+ {
190
+ const struct tc_action_ops * ops = a -> ops ;
191
+ int ret ;
192
+
193
+ ret = __tcf_idr_release (a , bind , false);
194
+ if (ret == ACT_P_DELETED )
195
+ module_put (ops -> owner );
196
+ return ret ;
197
+ }
198
+ EXPORT_SYMBOL (tcf_idr_release );
188
199
189
200
static size_t tcf_action_shared_attrs_size (const struct tc_action * act )
190
201
{
@@ -493,6 +504,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
493
504
}
494
505
495
506
p -> idrinfo = idrinfo ;
507
+ __module_get (ops -> owner );
496
508
p -> ops = ops ;
497
509
* a = p ;
498
510
return 0 ;
@@ -992,7 +1004,8 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
992
1004
struct tc_action * tcf_action_init_1 (struct net * net , struct tcf_proto * tp ,
993
1005
struct nlattr * nla , struct nlattr * est ,
994
1006
char * name , int ovr , int bind ,
995
- struct tc_action_ops * a_o , bool rtnl_held ,
1007
+ struct tc_action_ops * a_o , int * init_res ,
1008
+ bool rtnl_held ,
996
1009
struct netlink_ext_ack * extack )
997
1010
{
998
1011
struct nla_bitfield32 flags = { 0 , 0 };
@@ -1028,23 +1041,14 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
1028
1041
}
1029
1042
if (err < 0 )
1030
1043
goto err_out ;
1044
+ * init_res = err ;
1031
1045
1032
1046
if (!name && tb [TCA_ACT_COOKIE ])
1033
1047
tcf_set_action_cookie (& a -> act_cookie , cookie );
1034
1048
1035
1049
if (!name )
1036
1050
a -> hw_stats = hw_stats ;
1037
1051
1038
- /* module count goes up only when brand new policy is created
1039
- * if it exists and is only bound to in a_o->init() then
1040
- * ACT_P_CREATED is not returned (a zero is).
1041
- */
1042
- if (err != ACT_P_CREATED )
1043
- module_put (a_o -> owner );
1044
-
1045
- if (!bind && ovr && err == ACT_P_CREATED )
1046
- refcount_set (& a -> tcfa_refcnt , 2 );
1047
-
1048
1052
return a ;
1049
1053
1050
1054
err_out :
@@ -1059,7 +1063,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
1059
1063
1060
1064
int tcf_action_init (struct net * net , struct tcf_proto * tp , struct nlattr * nla ,
1061
1065
struct nlattr * est , char * name , int ovr , int bind ,
1062
- struct tc_action * actions [], size_t * attr_size ,
1066
+ struct tc_action * actions [], int init_res [], size_t * attr_size ,
1063
1067
bool rtnl_held , struct netlink_ext_ack * extack )
1064
1068
{
1065
1069
struct tc_action_ops * ops [TCA_ACT_MAX_PRIO ] = {};
@@ -1087,7 +1091,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
1087
1091
1088
1092
for (i = 1 ; i <= TCA_ACT_MAX_PRIO && tb [i ]; i ++ ) {
1089
1093
act = tcf_action_init_1 (net , tp , tb [i ], est , name , ovr , bind ,
1090
- ops [i - 1 ], rtnl_held , extack );
1094
+ ops [i - 1 ], & init_res [i - 1 ], rtnl_held ,
1095
+ extack );
1091
1096
if (IS_ERR (act )) {
1092
1097
err = PTR_ERR (act );
1093
1098
goto err ;
@@ -1103,7 +1108,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
1103
1108
tcf_idr_insert_many (actions );
1104
1109
1105
1110
* attr_size = tcf_action_full_attrs_size (sz );
1106
- return i - 1 ;
1111
+ err = i - 1 ;
1112
+ goto err_mod ;
1107
1113
1108
1114
err :
1109
1115
tcf_action_destroy (actions , bind );
@@ -1500,21 +1506,26 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
1500
1506
struct netlink_ext_ack * extack )
1501
1507
{
1502
1508
size_t attr_size = 0 ;
1503
- int loop , ret ;
1509
+ int loop , ret , i ;
1504
1510
struct tc_action * actions [TCA_ACT_MAX_PRIO ] = {};
1511
+ int init_res [TCA_ACT_MAX_PRIO ] = {};
1505
1512
1506
1513
for (loop = 0 ; loop < 10 ; loop ++ ) {
1507
1514
ret = tcf_action_init (net , NULL , nla , NULL , NULL , ovr , 0 ,
1508
- actions , & attr_size , true, extack );
1515
+ actions , init_res , & attr_size , true, extack );
1509
1516
if (ret != - EAGAIN )
1510
1517
break ;
1511
1518
}
1512
1519
1513
1520
if (ret < 0 )
1514
1521
return ret ;
1515
1522
ret = tcf_add_notify (net , n , actions , portid , attr_size , extack );
1516
- if (ovr )
1517
- tcf_action_put_many (actions );
1523
+
1524
+ /* only put existing actions */
1525
+ for (i = 0 ; i < TCA_ACT_MAX_PRIO ; i ++ )
1526
+ if (init_res [i ] == ACT_P_CREATED )
1527
+ actions [i ] = NULL ;
1528
+ tcf_action_put_many (actions );
1518
1529
1519
1530
return ret ;
1520
1531
}
0 commit comments