diff options
Diffstat (limited to 'net/sched/act_api.c')
-rw-r--r-- | net/sched/act_api.c | 18 |
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 | ||
665 | static 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 | |||
665 | static int tcf_action_put(struct tc_action *p) | 672 | static 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 | } |