aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@coreworks.de>2005-01-12 00:10:34 +0100
committerPatrick McHardy <kaber@coreworks.de>2005-01-12 00:10:34 +0100
commit8d7c694553dcb5f84f5018c1e7727f5ab4c33d79 (patch)
tree0da59b8e3f973cb3c284c854e6c594ed4d80d75b /net
parentc2e2849f0cea17c47cecfa0064c3d01cd58422da (diff)
downloadhistory-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.c23
-rw-r--r--net/sched/cls_api.c25
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;
}