net: sch: api: add extack support in qdisc_create_dflt
authorAlexander Aring <aring@mojatatu.com>
Wed, 20 Dec 2017 17:35:21 +0000 (12:35 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 21 Dec 2017 17:32:51 +0000 (12:32 -0500)
This patch adds extack support for the function qdisc_create_dflt which is
a common used function in the tc subsystem. Callers which are interested
in the receiving error can assign extack to get a more detailed
information why qdisc_create_dflt failed. The function qdisc_create_dflt
will also call an init callback which can fail by any per-qdisc specific
handling.

Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
18 files changed:
include/net/pkt_sched.h
include/net/sch_generic.h
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_fifo.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_mq.c
net/sched/sch_mqprio.c
net/sched/sch_multiq.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_red.c
net/sched/sch_sfb.c
net/sched/sch_tbf.c

index a4f21c0b4a43636d14849d91744c5987dc576125..e2c75f52557bc977d4b9d75d9c8bc44ad8201b48 100644 (file)
@@ -89,7 +89,8 @@ extern struct Qdisc_ops pfifo_head_drop_qdisc_ops;
 
 int fifo_set_limit(struct Qdisc *q, unsigned int limit);
 struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
-                              unsigned int limit);
+                              unsigned int limit,
+                              struct netlink_ext_ack *extack);
 
 int register_qdisc(struct Qdisc_ops *qops);
 int unregister_qdisc(struct Qdisc_ops *qops);
index faf6b2dbc1b29f10b968773c3ab6d0ef6e76a7b9..ac029d5d88e412526a195844f762c6c363266635 100644 (file)
@@ -474,7 +474,8 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
                          const struct Qdisc_ops *ops,
                          struct netlink_ext_ack *extack);
 struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
-                               const struct Qdisc_ops *ops, u32 parentid);
+                               const struct Qdisc_ops *ops, u32 parentid,
+                               struct netlink_ext_ack *extack);
 void __qdisc_calculate_pkt_len(struct sk_buff *skb,
                               const struct qdisc_size_table *stab);
 int skb_do_redirect(struct sk_buff *);
index 493d5c25d83aff1a7b92d323e494a764e44877be..cd49afca96177bed5c37caa19e4f19b0c452a0a1 100644 (file)
@@ -290,7 +290,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
                goto err_out;
        }
 
-       flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
+       flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+                                   extack);
        if (!flow->q)
                flow->q = &noop_qdisc;
        pr_debug("atm_tc_change: qdisc %p\n", flow->q);
@@ -546,7 +547,7 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt,
        INIT_LIST_HEAD(&p->link.list);
        list_add(&p->link.list, &p->flows);
        p->link.q = qdisc_create_dflt(sch->dev_queue,
-                                     &pfifo_qdisc_ops, sch->handle);
+                                     &pfifo_qdisc_ops, sch->handle, extack);
        if (!p->link.q)
                p->link.q = &noop_qdisc;
        pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
index 248ea26997b91eded41adc121acb4b657fb2869e..efe5bf15b031ed787a649bb57c3cd07049348355 100644 (file)
@@ -1172,7 +1172,7 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
        q->link.common.classid = sch->handle;
        q->link.qdisc = sch;
        q->link.q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                     sch->handle);
+                                     sch->handle, NULL);
        if (!q->link.q)
                q->link.q = &noop_qdisc;
        else
@@ -1376,8 +1376,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
        struct cbq_class *cl = (struct cbq_class *)arg;
 
        if (new == NULL) {
-               new = qdisc_create_dflt(sch->dev_queue,
-                                       &pfifo_qdisc_ops, cl->common.classid);
+               new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                       cl->common.classid, extack);
                if (new == NULL)
                        return -ENOBUFS;
        }
@@ -1596,7 +1596,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 
        cl->R_tab = rtab;
        rtab = NULL;
-       cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
+       cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+                                 NULL);
        if (!cl->q)
                cl->q = &noop_qdisc;
        else
index 9dfff065e27d03a4f181210d72e1b7aa7ca2e6de..bf638ce57c50eae22de1452e4c112724311d8f50 100644 (file)
@@ -114,7 +114,8 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        cl->common.classid = classid;
        cl->quantum        = quantum;
        cl->qdisc          = qdisc_create_dflt(sch->dev_queue,
-                                              &pfifo_qdisc_ops, classid);
+                                              &pfifo_qdisc_ops, classid,
+                                              NULL);
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
        else
@@ -209,8 +210,8 @@ static int drr_graft_class(struct Qdisc *sch, unsigned long arg,
        struct drr_class *cl = (struct drr_class *)arg;
 
        if (new == NULL) {
-               new = qdisc_create_dflt(sch->dev_queue,
-                                       &pfifo_qdisc_ops, cl->common.classid);
+               new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                       cl->common.classid, NULL);
                if (new == NULL)
                        new = &noop_qdisc;
        }
index 63f523b5e282a7e0665c9867f699114d65bd2fe4..049714c57075c6acb212e4cfb47d962fda67b2bb 100644 (file)
@@ -71,7 +71,7 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
 
        if (new == NULL) {
                new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                       sch->handle);
+                                       sch->handle, NULL);
                if (new == NULL)
                        new = &noop_qdisc;
        }
@@ -381,7 +381,8 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
        p->default_index = default_index;
        p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
 
-       p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle);
+       p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle,
+                                NULL);
        if (p->q == NULL)
                p->q = &noop_qdisc;
        else
index c65f23c70f401aca38a2ec63ff823203077e629f..24893d3b5d229d27ec05760815ab222ae052271b 100644 (file)
@@ -166,12 +166,14 @@ int fifo_set_limit(struct Qdisc *q, unsigned int limit)
 EXPORT_SYMBOL(fifo_set_limit);
 
 struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
-                              unsigned int limit)
+                              unsigned int limit,
+                              struct netlink_ext_ack *extack)
 {
        struct Qdisc *q;
        int err = -ENOMEM;
 
-       q = qdisc_create_dflt(sch->dev_queue, ops, TC_H_MAKE(sch->handle, 1));
+       q = qdisc_create_dflt(sch->dev_queue, ops, TC_H_MAKE(sch->handle, 1),
+                             extack);
        if (q) {
                err = fifo_set_limit(q, limit);
                if (err < 0) {
index 34ef4366f8e0a674652fc34d1fb6bf6c414732a3..10aaa3b615ce8b9382732fca95dd28838026ef1b 100644 (file)
@@ -830,21 +830,24 @@ errout:
 
 struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
                                const struct Qdisc_ops *ops,
-                               unsigned int parentid)
+                               unsigned int parentid,
+                               struct netlink_ext_ack *extack)
 {
        struct Qdisc *sch;
 
-       if (!try_module_get(ops->owner))
+       if (!try_module_get(ops->owner)) {
+               NL_SET_ERR_MSG(extack, "Failed to increase module reference counter");
                return NULL;
+       }
 
-       sch = qdisc_alloc(dev_queue, ops, NULL);
+       sch = qdisc_alloc(dev_queue, ops, extack);
        if (IS_ERR(sch)) {
                module_put(ops->owner);
                return NULL;
        }
        sch->parent = parentid;
 
-       if (!ops->init || ops->init(sch, NULL, NULL) == 0)
+       if (!ops->init || ops->init(sch, NULL, extack) == 0)
                return sch;
 
        qdisc_destroy(sch);
@@ -956,7 +959,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
        if (dev->priv_flags & IFF_NO_QUEUE)
                ops = &noqueue_qdisc_ops;
 
-       qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT);
+       qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT, NULL);
        if (!qdisc) {
                netdev_info(dev, "activation failed\n");
                return;
@@ -979,7 +982,7 @@ static void attach_default_qdiscs(struct net_device *dev)
                dev->qdisc = txq->qdisc_sleeping;
                qdisc_refcount_inc(dev->qdisc);
        } else {
-               qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);
+               qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT, NULL);
                if (qdisc) {
                        dev->qdisc = qdisc;
                        qdisc->ops->attach(qdisc);
index 9ae288fcbed8420af3b8d31706cfcf0d5d036526..3ae9877ea2057d0ba517c84d38f6ba6a79ff6ef8 100644 (file)
@@ -1062,8 +1062,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        cl->cl_common.classid = classid;
        cl->sched     = q;
        cl->cl_parent = parent;
-       cl->qdisc = qdisc_create_dflt(sch->dev_queue,
-                                     &pfifo_qdisc_ops, classid);
+       cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                     classid, NULL);
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
        else
@@ -1185,7 +1185,7 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
                return -EINVAL;
        if (new == NULL) {
                new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                       cl->cl_common.classid);
+                                       cl->cl_common.classid, NULL);
                if (new == NULL)
                        new = &noop_qdisc;
        }
@@ -1416,7 +1416,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
        q->root.cl_common.classid = sch->handle;
        q->root.sched   = q;
        q->root.qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                         sch->handle);
+                                         sch->handle, NULL);
        if (q->root.qdisc == NULL)
                q->root.qdisc = &noop_qdisc;
        else
index 54e1f860f1e58d52c9e8b3c036044718cf3021c5..1ea9846cc6ce91f4f0455d2c493e31750fd65478 100644 (file)
@@ -1180,7 +1180,7 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
                return -EINVAL;
        if (new == NULL &&
            (new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                    cl->common.classid)) == NULL)
+                                    cl->common.classid, extack)) == NULL)
                return -ENOBUFS;
 
        *old = qdisc_replace(sch, new, &cl->un.leaf.q);
@@ -1290,7 +1290,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
 
        if (!cl->level && htb_parent_last_child(cl)) {
                new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                         cl->parent->common.classid);
+                                         cl->parent->common.classid,
+                                         NULL);
                last_child = 1;
        }
 
@@ -1426,8 +1427,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                 * so that can't be used inside of sch_tree_lock
                 * -- thanks to Karlis Peisenieks
                 */
-               new_q = qdisc_create_dflt(sch->dev_queue,
-                                         &pfifo_qdisc_ops, classid);
+               new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                         classid, NULL);
                sch_tree_lock(sch);
                if (parent && !parent->level) {
                        unsigned int qlen = parent->un.leaf.q->q.qlen;
index 50292e470432b01fbf5b767c2ee193450c259f58..f062a18e9162ad215343023b69c3e87a81cf6651 100644 (file)
@@ -61,7 +61,8 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt,
                dev_queue = netdev_get_tx_queue(dev, ntx);
                qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx),
                                          TC_H_MAKE(TC_H_MAJ(sch->handle),
-                                                   TC_H_MIN(ntx + 1)));
+                                                   TC_H_MIN(ntx + 1)),
+                                         extack);
                if (!qdisc)
                        return -ENOMEM;
                priv->qdiscs[ntx] = qdisc;
index 29071cf329f33fcddd43a4d5509cedc77a1e7e01..0e9d761cdd80a18bdfc824503dcd8e5a8ee5c596 100644 (file)
@@ -230,7 +230,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,
                qdisc = qdisc_create_dflt(dev_queue,
                                          get_default_qdisc_ops(dev, i),
                                          TC_H_MAKE(TC_H_MAJ(sch->handle),
-                                                   TC_H_MIN(i + 1)));
+                                                   TC_H_MIN(i + 1)), extack);
                if (!qdisc)
                        return -ENOMEM;
 
index 35cbaf8bd96a4a8de4b956990a57d0ecf63324d7..1da7ea8de0ad37a3ee1615b0f5aae68391b08842 100644 (file)
@@ -216,7 +216,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
                        child = qdisc_create_dflt(sch->dev_queue,
                                                  &pfifo_qdisc_ops,
                                                  TC_H_MAKE(sch->handle,
-                                                           i + 1));
+                                                           i + 1), extack);
                        if (child) {
                                sch_tree_lock(sch);
                                old = q->queues[i];
index 502352762f03fc79b34f380dee48dc7be38cbfbd..fe1510eb111ff506c047063cbe516e5742d7343f 100644 (file)
@@ -176,7 +176,8 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
        /* Before commit, make sure we can allocate all new qdiscs */
        for (i = oldbands; i < qopt->bands; i++) {
                queues[i] = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
-                                             TC_H_MAKE(sch->handle, i + 1));
+                                             TC_H_MAKE(sch->handle, i + 1),
+                                             extack);
                if (!queues[i]) {
                        while (i > oldbands)
                                qdisc_destroy(queues[--i]);
index 6ab58509cf49d749c9198e6fc52b6957a23afda3..bb1a9c11fc549a170172e3d7deaf9693b18e7332 100644 (file)
@@ -480,8 +480,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        cl->common.classid = classid;
        cl->deficit = lmax;
 
-       cl->qdisc = qdisc_create_dflt(sch->dev_queue,
-                                     &pfifo_qdisc_ops, classid);
+       cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                     classid, NULL);
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
 
@@ -601,8 +601,8 @@ static int qfq_graft_class(struct Qdisc *sch, unsigned long arg,
        struct qfq_class *cl = (struct qfq_class *)arg;
 
        if (new == NULL) {
-               new = qdisc_create_dflt(sch->dev_queue,
-                                       &pfifo_qdisc_ops, cl->common.classid);
+               new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                       cl->common.classid, NULL);
                if (new == NULL)
                        new = &noop_qdisc;
        }
index ea7d400b9eb201351316c20e5e7c3ee93c5128d2..ec0bd36e09a90d736932c04e2c922b18b47b8ca5 100644 (file)
@@ -225,7 +225,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt,
                return -EINVAL;
 
        if (ctl->limit > 0) {
-               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
+               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit,
+                                        extack);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
index a1a11ded8e4f574d67230de841ca61d623f972cb..7cbdad8419b7f4d9c6441fce0b822db1d058b176 100644 (file)
@@ -513,7 +513,7 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt,
        if (limit == 0)
                limit = qdisc_dev(sch)->tx_queue_len;
 
-       child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit);
+       child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit, extack);
        if (IS_ERR(child))
                return PTR_ERR(child);
 
index 1ab53ff80f46294607d3a95a8be258a89ae473b4..83e76d046993ec568f3425d25ff23fe5b42965ef 100644 (file)
@@ -386,7 +386,8 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
                if (err)
                        goto done;
        } else if (qopt->limit > 0) {
-               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
+               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit,
+                                        extack);
                if (IS_ERR(child)) {
                        err = PTR_ERR(child);
                        goto done;