netfilter: xtables: add const qualifiers
[safe/jmp/linux-2.6] / net / sched / sch_api.c
index d71f12b..6cd4910 100644 (file)
@@ -678,6 +678,11 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                if (dev->flags & IFF_UP)
                        dev_deactivate(dev);
 
+               if (new && new->ops->attach) {
+                       new->ops->attach(new);
+                       num_q = 0;
+               }
+
                for (i = 0; i < num_q; i++) {
                        struct netdev_queue *dev_queue = &dev->rx_queue;
 
@@ -688,13 +693,18 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                        if (new && i > 0)
                                atomic_inc(&new->refcnt);
 
-                       qdisc_destroy(old);
+                       if (!ingress)
+                               qdisc_destroy(old);
                }
 
-               notify_and_destroy(skb, n, classid, dev->qdisc, new);
-               if (new)
-                       atomic_inc(&new->refcnt);
-               dev->qdisc = new ? : &noop_qdisc;
+               if (!ingress) {
+                       notify_and_destroy(skb, n, classid, dev->qdisc, new);
+                       if (new && !new->ops->attach)
+                               atomic_inc(&new->refcnt);
+                       dev->qdisc = new ? : &noop_qdisc;
+               } else {
+                       notify_and_destroy(skb, n, classid, old, new);
+               }
 
                if (dev->flags & IFF_UP)
                        dev_activate(dev);
@@ -728,7 +738,8 @@ static struct lock_class_key qdisc_rx_lock;
 
 static struct Qdisc *
 qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
-            u32 parent, u32 handle, struct nlattr **tca, int *errp)
+            struct Qdisc *p, u32 parent, u32 handle,
+            struct nlattr **tca, int *errp)
 {
        int err;
        struct nlattr *kind = tca[TCA_KIND];
@@ -798,31 +809,28 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
                        stab = qdisc_get_stab(tca[TCA_STAB]);
                        if (IS_ERR(stab)) {
                                err = PTR_ERR(stab);
-                               goto err_out3;
+                               goto err_out4;
                        }
                        sch->stab = stab;
                }
                if (tca[TCA_RATE]) {
                        spinlock_t *root_lock;
 
+                       err = -EOPNOTSUPP;
+                       if (sch->flags & TCQ_F_MQROOT)
+                               goto err_out4;
+
                        if ((sch->parent != TC_H_ROOT) &&
-                           !(sch->flags & TCQ_F_INGRESS))
+                           !(sch->flags & TCQ_F_INGRESS) &&
+                           (!p || !(p->flags & TCQ_F_MQROOT)))
                                root_lock = qdisc_root_sleeping_lock(sch);
                        else
                                root_lock = qdisc_lock(sch);
 
                        err = gen_new_estimator(&sch->bstats, &sch->rate_est,
                                                root_lock, tca[TCA_RATE]);
-                       if (err) {
-                               /*
-                                * Any broken qdiscs that would require
-                                * a ops->reset() here? The qdisc was never
-                                * in action so it shouldn't be necessary.
-                                */
-                               if (ops->destroy)
-                                       ops->destroy(sch);
-                               goto err_out3;
-                       }
+                       if (err)
+                               goto err_out4;
                }
 
                qdisc_list_add(sch);
@@ -830,7 +838,6 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
                return sch;
        }
 err_out3:
-       qdisc_put_stab(sch->stab);
        dev_put(dev);
        kfree((char *) sch - sch->padded);
 err_out2:
@@ -838,6 +845,16 @@ err_out2:
 err_out:
        *errp = err;
        return NULL;
+
+err_out4:
+       /*
+        * Any broken qdiscs that would require a ops->reset() here?
+        * The qdisc was never in action so it shouldn't be necessary.
+        */
+       qdisc_put_stab(sch->stab);
+       if (ops->destroy)
+               ops->destroy(sch);
+       goto err_out3;
 }
 
 static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
@@ -862,13 +879,16 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
        qdisc_put_stab(sch->stab);
        sch->stab = stab;
 
-       if (tca[TCA_RATE])
+       if (tca[TCA_RATE]) {
                /* NB: ignores errors from replace_estimator
                   because change can't be undone. */
+               if (sch->flags & TCQ_F_MQROOT)
+                       goto out;
                gen_replace_estimator(&sch->bstats, &sch->rate_est,
                                            qdisc_root_sleeping_lock(sch),
                                            tca[TCA_RATE]);
-
+       }
+out:
        return 0;
 }
 
@@ -927,7 +947,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        struct Qdisc *p = NULL;
        int err;
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return -EINVAL;
 
        if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
@@ -989,7 +1009,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        struct Qdisc *q, *p;
        int err;
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return -EINVAL;
 
 replay:
@@ -1092,13 +1112,23 @@ create_n_graft:
        if (!(n->nlmsg_flags&NLM_F_CREATE))
                return -ENOENT;
        if (clid == TC_H_INGRESS)
-               q = qdisc_create(dev, &dev->rx_queue,
+               q = qdisc_create(dev, &dev->rx_queue, p,
                                 tcm->tcm_parent, tcm->tcm_parent,
                                 tca, &err);
-       else
-               q = qdisc_create(dev, netdev_get_tx_queue(dev, 0),
+       else {
+               struct netdev_queue *dev_queue;
+
+               if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
+                       dev_queue = p->ops->cl_ops->select_queue(p, tcm);
+               else if (p)
+                       dev_queue = p->dev_queue;
+               else
+                       dev_queue = netdev_get_tx_queue(dev, 0);
+
+               q = qdisc_create(dev, dev_queue, p,
                                 tcm->tcm_parent, tcm->tcm_handle,
                                 tca, &err);
+       }
        if (q == NULL) {
                if (err == -EAGAIN)
                        goto replay;
@@ -1149,7 +1179,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
                goto nla_put_failure;
 
        if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
-           gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
+           gnet_stats_copy_rate_est(&d, &q->bstats, &q->rate_est) < 0 ||
            gnet_stats_copy_queue(&d, &q->qstats) < 0)
                goto nla_put_failure;
 
@@ -1244,14 +1274,15 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
        int s_idx, s_q_idx;
        struct net_device *dev;
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return 0;
 
        s_idx = cb->args[0];
        s_q_idx = q_idx = cb->args[1];
-       read_lock(&dev_base_lock);
+
+       rcu_read_lock();
        idx = 0;
-       for_each_netdev(&init_net, dev) {
+       for_each_netdev_rcu(&init_net, dev) {
                struct netdev_queue *dev_queue;
 
                if (idx < s_idx)
@@ -1272,7 +1303,7 @@ cont:
        }
 
 done:
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
 
        cb->args[0] = idx;
        cb->args[1] = q_idx;
@@ -1303,7 +1334,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        u32 qid = TC_H_MAJ(clid);
        int err;
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return -EINVAL;
 
        if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
@@ -1426,6 +1457,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
        nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
        tcm = NLMSG_DATA(nlh);
        tcm->tcm_family = AF_UNSPEC;
+       tcm->tcm__pad1 = 0;
+       tcm->tcm__pad2 = 0;
        tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
        tcm->tcm_parent = q->handle;
        tcm->tcm_handle = q->handle;
@@ -1543,7 +1576,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
        struct net_device *dev;
        int t, s_t;
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return 0;
 
        if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
@@ -1674,6 +1707,8 @@ static int __init pktsched_init(void)
 {
        register_qdisc(&pfifo_qdisc_ops);
        register_qdisc(&bfifo_qdisc_ops);
+       register_qdisc(&pfifo_head_drop_qdisc_ops);
+       register_qdisc(&mq_qdisc_ops);
        proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
 
        rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);