===== net/sched/sch_api.c 1.41 vs edited =====
--- 1.41/net/sched/sch_api.c 2004-11-05 16:34:45 -08:00
+++ edited/net/sched/sch_api.c 2004-11-09 15:57:19 -08:00
@@ -396,17 +396,30 @@
struct Qdisc_ops *ops;
int size;
+ err = -EINVAL;
ops = qdisc_lookup_ops(kind);
#ifdef CONFIG_KMOD
if (ops==NULL && tca[TCA_KIND-1] != NULL) {
if (RTA_PAYLOAD(kind) <= IFNAMSIZ) {
+ rtnl_unlock();
request_module("sch_%s", (char*)RTA_DATA(kind));
+ rtnl_lock();
+
ops = qdisc_lookup_ops(kind);
+
+ /* 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 (ops != NULL)
+ err = -EAGAIN;
+ goto err_out;
}
}
#endif
- err = -EINVAL;
if (ops == NULL)
goto err_out;
err = -EBUSY;
@@ -600,14 +613,19 @@
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
- struct tcmsg *tcm = NLMSG_DATA(n);
- struct rtattr **tca = arg;
+ struct tcmsg *tcm;
+ struct rtattr **tca;
struct net_device *dev;
- u32 clid = tcm->tcm_parent;
- struct Qdisc *q = NULL;
- struct Qdisc *p = NULL;
+ u32 clid;
+ struct Qdisc *q, *p;
int err;
+replay:
+ tcm = NLMSG_DATA(n);
+ tca = arg;
+ clid = tcm->tcm_parent;
+ q = p = NULL;
+
if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
return -ENODEV;
@@ -701,8 +719,14 @@
q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
else
q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
- if (q == NULL)
+ if (q == NULL) {
+ if (err == -EAGAIN) {
+ /* Replay the request. */
+ dev_put(dev);
+ goto replay;
+ }
return err;
+ }
graft:
if (1) {