Commit 8d7c6945 authored by Patrick McHardy's avatar Patrick McHardy

[PKT_SCHED]: act_api.c: drop rtnl for loading modules

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent c2e2849f
...@@ -291,16 +291,28 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, ...@@ -291,16 +291,28 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
goto err_out; goto err_out;
} }
*err = -ENOENT;
a_o = tc_lookup_action_n(act_name); a_o = tc_lookup_action_n(act_name);
#ifdef CONFIG_KMOD
if (a_o == NULL) { if (a_o == NULL) {
#ifdef CONFIG_KMOD
rtnl_unlock();
request_module(act_name); request_module(act_name);
rtnl_lock();
a_o = tc_lookup_action_n(act_name); a_o = tc_lookup_action_n(act_name);
}
/* We dropped the RTNL semaphore in order to
* perform the module load. So, even if we
* succeeded in loading the module we have to
* tell the caller to replay the request. We
* indicate this using -EAGAIN.
*/
if (a_o != NULL) {
*err = -EAGAIN;
goto err_mod;
}
#endif #endif
if (a_o == NULL)
goto err_out; goto err_out;
}
*err = -ENOMEM; *err = -ENOMEM;
a = kmalloc(sizeof(*a), GFP_KERNEL); a = kmalloc(sizeof(*a), GFP_KERNEL);
...@@ -740,7 +752,10 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -740,7 +752,10 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
*/ */
if (n->nlmsg_flags&NLM_F_REPLACE) if (n->nlmsg_flags&NLM_F_REPLACE)
ovr = 1; ovr = 1;
replay:
ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr); ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr);
if (ret == -EAGAIN)
goto replay;
break; break;
case RTM_DELACTION: case RTM_DELACTION:
ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION); ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION);
......
...@@ -130,22 +130,30 @@ static __inline__ u32 tcf_auto_prio(struct tcf_proto *tp) ...@@ -130,22 +130,30 @@ static __inline__ u32 tcf_auto_prio(struct tcf_proto *tp)
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{ {
struct rtattr **tca = arg; struct rtattr **tca;
struct tcmsg *t = NLMSG_DATA(n); struct tcmsg *t;
u32 protocol = TC_H_MIN(t->tcm_info); u32 protocol;
u32 prio = TC_H_MAJ(t->tcm_info); u32 prio;
u32 nprio = prio; u32 nprio;
u32 parent = t->tcm_parent; u32 parent;
struct net_device *dev; struct net_device *dev;
struct Qdisc *q; struct Qdisc *q;
struct tcf_proto **back, **chain; struct tcf_proto **back, **chain;
struct tcf_proto *tp = NULL; struct tcf_proto *tp;
struct tcf_proto_ops *tp_ops; struct tcf_proto_ops *tp_ops;
struct Qdisc_class_ops *cops; struct Qdisc_class_ops *cops;
unsigned long cl = 0; unsigned long cl = 0;
unsigned long fh; unsigned long fh;
int err; int err;
replay:
tca = arg;
t = NLMSG_DATA(n);
protocol = TC_H_MIN(t->tcm_info);
prio = TC_H_MAJ(t->tcm_info);
nprio = prio;
parent = t->tcm_parent;
if (prio == 0) { if (prio == 0) {
/* If no priority is given, user wants we allocated it. */ /* If no priority is given, user wants we allocated it. */
if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE)) if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
...@@ -294,6 +302,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) ...@@ -294,6 +302,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
errout: errout:
if (cl) if (cl)
cops->put(q, cl); cops->put(q, cl);
if (err == -EAGAIN)
/* Replay the request. */
goto replay;
return err; return err;
} }
......
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