diff options
author | Patrick McHardy <kaber@coreworks.de> | 2005-01-12 00:10:34 +0100 |
---|---|---|
committer | Patrick McHardy <kaber@coreworks.de> | 2005-01-12 00:10:34 +0100 |
commit | 8d7c694553dcb5f84f5018c1e7727f5ab4c33d79 (patch) | |
tree | 0da59b8e3f973cb3c284c854e6c594ed4d80d75b /net | |
parent | c2e2849f0cea17c47cecfa0064c3d01cd58422da (diff) | |
download | history-8d7c694553dcb5f84f5018c1e7727f5ab4c33d79.tar.gz |
[PKT_SCHED]: act_api.c: drop rtnl for loading modules
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/act_api.c | 23 | ||||
-rw-r--r-- | net/sched/cls_api.c | 25 |
2 files changed, 37 insertions, 11 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 4fb53331909dc9..349e3bad9d10ce 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -291,16 +291,28 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, goto err_out; } - *err = -ENOENT; a_o = tc_lookup_action_n(act_name); -#ifdef CONFIG_KMOD if (a_o == NULL) { +#ifdef CONFIG_KMOD + rtnl_unlock(); request_module(act_name); + rtnl_lock(); + 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 - if (a_o == NULL) goto err_out; + } *err = -ENOMEM; a = kmalloc(sizeof(*a), GFP_KERNEL); @@ -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) ovr = 1; +replay: ret = tcf_action_add(tca[TCA_ACT_TAB-1], n, pid, ovr); + if (ret == -EAGAIN) + goto replay; break; case RTM_DELACTION: ret = tca_action_gd(tca[TCA_ACT_TAB-1], n, pid, RTM_DELACTION); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index c2e298468d27c8..b0a2e07f7bc1c4 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -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) { - struct rtattr **tca = arg; - struct tcmsg *t = NLMSG_DATA(n); - u32 protocol = TC_H_MIN(t->tcm_info); - u32 prio = TC_H_MAJ(t->tcm_info); - u32 nprio = prio; - u32 parent = t->tcm_parent; + struct rtattr **tca; + struct tcmsg *t; + u32 protocol; + u32 prio; + u32 nprio; + u32 parent; struct net_device *dev; struct Qdisc *q; struct tcf_proto **back, **chain; - struct tcf_proto *tp = NULL; + struct tcf_proto *tp; struct tcf_proto_ops *tp_ops; struct Qdisc_class_ops *cops; unsigned long cl = 0; unsigned long fh; 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 no priority is given, user wants we allocated it. */ 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) errout: if (cl) cops->put(q, cl); + if (err == -EAGAIN) + /* Replay the request. */ + goto replay; return err; } |