Commit 6d141d44 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[PKT_SCHED]: Clean up tcf_action_init memory handling

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8fb8f6c6
...@@ -87,8 +87,8 @@ extern int tcf_register_action(struct tc_action_ops *a); ...@@ -87,8 +87,8 @@ extern int tcf_register_action(struct tc_action_ops *a);
extern int tcf_unregister_action(struct tc_action_ops *a); extern int tcf_unregister_action(struct tc_action_ops *a);
extern void tcf_action_destroy(struct tc_action *a, int bind); extern void tcf_action_destroy(struct tc_action *a, int bind);
extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res); extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind); extern struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est, char *n, int ovr, int bind, int *err);
extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind); extern struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, char *n, int ovr, int bind, int *err);
extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int); extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int); extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int); extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
......
...@@ -70,17 +70,10 @@ tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action, ...@@ -70,17 +70,10 @@ tcf_change_act_police(struct tcf_proto *tp, struct tc_action **action,
int ret; int ret;
struct tc_action *act; struct tc_action *act;
act = kmalloc(sizeof(*act), GFP_KERNEL); act = tcf_action_init_1(act_police_tlv, rate_tlv, "police",
if (NULL == act) TCA_ACT_NOREPLACE, TCA_ACT_BIND, &ret);
return -ENOMEM; if (act == NULL)
memset(act, 0, sizeof(*act));
ret = tcf_action_init_1(act_police_tlv, rate_tlv, act, "police",
TCA_ACT_NOREPLACE, TCA_ACT_BIND);
if (ret < 0) {
tcf_action_destroy(act, TCA_ACT_UNBIND);
return ret; return ret;
}
act->type = TCA_OLD_COMPAT; act->type = TCA_OLD_COMPAT;
...@@ -103,17 +96,10 @@ tcf_change_act(struct tcf_proto *tp, struct tc_action **action, ...@@ -103,17 +96,10 @@ tcf_change_act(struct tcf_proto *tp, struct tc_action **action,
int ret; int ret;
struct tc_action *act; struct tc_action *act;
act = kmalloc(sizeof(*act), GFP_KERNEL); act = tcf_action_init(act_tlv, rate_tlv, NULL,
if (NULL == act) TCA_ACT_NOREPLACE, TCA_ACT_BIND, &ret);
return -ENOMEM; if (act == NULL)
memset(act, 0, sizeof(*act));
ret = tcf_action_init(act_tlv, rate_tlv, act, NULL,
TCA_ACT_NOREPLACE, TCA_ACT_BIND);
if (ret < 0) {
tcf_action_destroy(act, TCA_ACT_UNBIND);
return ret; return ret;
}
if (*action) { if (*action) {
tcf_tree_lock(tp); tcf_tree_lock(tp);
......
...@@ -294,14 +294,16 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int re ...@@ -294,14 +294,16 @@ int tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int re
} }
int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a, char *name, int ovr, int bind ) struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
char *name, int ovr, int bind, int *err)
{ {
struct tc_action *a;
struct tc_action_ops *a_o; struct tc_action_ops *a_o;
char act_name[4 + IFNAMSIZ + 1]; char act_name[4 + IFNAMSIZ + 1];
struct rtattr *tb[TCA_ACT_MAX+1]; struct rtattr *tb[TCA_ACT_MAX+1];
struct rtattr *kind = NULL; struct rtattr *kind = NULL;
int err = -EINVAL; *err = -EINVAL;
if (NULL == name) { if (NULL == name) {
if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) if (rtattr_parse(tb, TCA_ACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta))<0)
...@@ -337,22 +339,25 @@ int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action * ...@@ -337,22 +339,25 @@ int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *
goto err_out; goto err_out;
} }
if (NULL == a) { a = kmalloc(sizeof(*a), GFP_KERNEL);
if (a == NULL) {
*err = -ENOMEM;
goto err_mod; goto err_mod;
} }
memset(a, 0, sizeof(*a));
/* backward compatibility for policer */ /* backward compatibility for policer */
if (NULL == name) { if (NULL == name) {
err = a_o->init(tb[TCA_ACT_OPTIONS-1], est, a, ovr, bind); *err = a_o->init(tb[TCA_ACT_OPTIONS-1], est, a, ovr, bind);
if (0 > err ) { if (*err < 0) {
err = -EINVAL; *err = -EINVAL;
goto err_mod; goto err_free;
} }
} else { } else {
err = a_o->init(rta, est, a, ovr, bind); *err = a_o->init(rta, est, a, ovr, bind);
if (0 > err ) { if (*err < 0) {
err = -EINVAL; *err = -EINVAL;
goto err_mod; goto err_free;
} }
} }
...@@ -360,60 +365,58 @@ int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action * ...@@ -360,60 +365,58 @@ int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *
if it exists and is only bound to in a_o->init() then if it exists and is only bound to in a_o->init() then
ACT_P_CREATED is not returned (a zero is). ACT_P_CREATED is not returned (a zero is).
*/ */
if (ACT_P_CREATED != err) { if (*err != ACT_P_CREATED)
module_put(a_o->owner); module_put(a_o->owner);
}
a->ops = a_o; a->ops = a_o;
DPRINTK("tcf_action_init_1: successfull %s \n",act_name); DPRINTK("tcf_action_init_1: successfull %s \n",act_name);
return 0; *err = 0;
return a;
err_free:
kfree(a);
err_mod: err_mod:
module_put(a_o->owner); module_put(a_o->owner);
err_out: err_out:
return err; return NULL;
} }
int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, char *name, int ovr , int bind) struct tc_action *tcf_action_init(struct rtattr *rta, struct rtattr *est,
char *name, int ovr, int bind, int *err)
{ {
struct rtattr *tb[TCA_ACT_MAX_PRIO+1]; struct rtattr *tb[TCA_ACT_MAX_PRIO+1];
struct tc_action *a = NULL, *act, *act_prev = NULL;
int i; int i;
struct tc_action *act = a, *a_s = a;
int err = -EINVAL;
if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta), RTA_PAYLOAD(rta))<0) if (rtattr_parse(tb, TCA_ACT_MAX_PRIO, RTA_DATA(rta),
return err; RTA_PAYLOAD(rta)) < 0) {
*err = -EINVAL;
return a;
}
for (i=0; i < TCA_ACT_MAX_PRIO ; i++) { for (i=0; i < TCA_ACT_MAX_PRIO; i++) {
if (tb[i]) { if (tb[i]) {
if (NULL == act) { act = tcf_action_init_1(tb[i], est, name, ovr, bind, err);
act = kmalloc(sizeof(*act),GFP_KERNEL); if (act == NULL) {
if (NULL == act) { printk("Error processing action order %d\n", i);
err = -ENOMEM;
goto bad_ret; goto bad_ret;
} }
memset(act, 0,sizeof(*act));
}
act->next = NULL;
if (0 > tcf_action_init_1(tb[i],est,act,name,ovr,bind)) {
printk("Error processing action order %d\n",i);
return err;
}
act->order = i+1; act->order = i+1;
if (a_s != act) { if (a == NULL)
a_s->next = act; a = act;
a_s = act; else
} act_prev->next = act;
act = NULL; act_prev = act;
} }
} }
return a;
return 0;
bad_ret: bad_ret:
if (a != NULL)
tcf_action_destroy(a, bind); tcf_action_destroy(a, bind);
return err; return NULL;
} }
int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a) int tcf_action_copy_stats (struct sk_buff *skb,struct tc_action *a)
...@@ -849,21 +852,9 @@ static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int o ...@@ -849,21 +852,9 @@ static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int o
struct tc_action *a = NULL; struct tc_action *a = NULL;
u32 seq = n->nlmsg_seq; u32 seq = n->nlmsg_seq;
act = kmalloc(sizeof(*act),GFP_KERNEL); act = tcf_action_init(rta, NULL, NULL, ovr, 0, &ret);
if (NULL == act) if (act == NULL)
return -ENOMEM;
memset(act, 0, sizeof(*act));
ret = tcf_action_init(rta, NULL,act,NULL,ovr,0);
/* NOTE: We have an all-or-none model
* This means that of any of the actions fail
* to update then all are undone.
* */
if (0 > ret) {
tcf_action_destroy(act, 0);
goto done; goto done;
}
/* dump then free all the actions after update; inserted policy /* dump then free all the actions after update; inserted policy
* stays intact * stays intact
...@@ -880,7 +871,6 @@ static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int o ...@@ -880,7 +871,6 @@ static int tcf_action_add(struct rtattr *rta, struct nlmsghdr *n, u32 pid, int o
} }
} }
done: done:
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment