aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/act_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/act_api.c')
-rw-r--r--net/sched/act_api.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index db83dac1e7f4..e12f8ef7baa4 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -662,6 +662,13 @@ int tcf_action_destroy(struct tc_action *actions[], int bind)
662 return ret; 662 return ret;
663} 663}
664 664
665static int tcf_action_destroy_1(struct tc_action *a, int bind)
666{
667 struct tc_action *actions[] = { a, NULL };
668
669 return tcf_action_destroy(actions, bind);
670}
671
665static int tcf_action_put(struct tc_action *p) 672static int tcf_action_put(struct tc_action *p)
666{ 673{
667 return __tcf_action_put(p, false); 674 return __tcf_action_put(p, false);
@@ -881,17 +888,16 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
881 if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) { 888 if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
882 err = tcf_action_goto_chain_init(a, tp); 889 err = tcf_action_goto_chain_init(a, tp);
883 if (err) { 890 if (err) {
884 struct tc_action *actions[] = { a, NULL }; 891 tcf_action_destroy_1(a, bind);
885
886 tcf_action_destroy(actions, bind);
887 NL_SET_ERR_MSG(extack, "Failed to init TC action chain"); 892 NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
888 return ERR_PTR(err); 893 return ERR_PTR(err);
889 } 894 }
890 } 895 }
891 896
892 if (!tcf_action_valid(a->tcfa_action)) { 897 if (!tcf_action_valid(a->tcfa_action)) {
893 NL_SET_ERR_MSG(extack, "invalid action value, using TC_ACT_UNSPEC instead"); 898 tcf_action_destroy_1(a, bind);
894 a->tcfa_action = TC_ACT_UNSPEC; 899 NL_SET_ERR_MSG(extack, "Invalid control action value");
900 return ERR_PTR(-EINVAL);
895 } 901 }
896 902
897 return a; 903 return a;
@@ -1173,6 +1179,7 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1173 struct tcf_idrinfo *idrinfo = a->idrinfo; 1179 struct tcf_idrinfo *idrinfo = a->idrinfo;
1174 u32 act_index = a->tcfa_index; 1180 u32 act_index = a->tcfa_index;
1175 1181
1182 actions[i] = NULL;
1176 if (tcf_action_put(a)) { 1183 if (tcf_action_put(a)) {
1177 /* last reference, action was deleted concurrently */ 1184 /* last reference, action was deleted concurrently */
1178 module_put(ops->owner); 1185 module_put(ops->owner);
@@ -1184,7 +1191,6 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1184 if (ret < 0) 1191 if (ret < 0)
1185 return ret; 1192 return ret;
1186 } 1193 }
1187 actions[i] = NULL;
1188 } 1194 }
1189 return 0; 1195 return 0;
1190} 1196}