net: sched: Pass root lock to Qdisc_ops.enqueue
authorPetr Machata <petrm@mellanox.com>
Fri, 26 Jun 2020 22:45:25 +0000 (01:45 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 30 Jun 2020 00:08:28 +0000 (17:08 -0700)
A following patch introduces qevents, points in qdisc algorithm where
packet can be processed by user-defined filters. Should this processing
lead to a situation where a new packet is to be enqueued on the same port,
holding the root lock would lead to deadlocks. To solve the issue, qevent
handler needs to unlock and relock the root lock when necessary.

To that end, add the root lock argument to the qdisc op enqueue, and
propagate throughout.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
35 files changed:
include/net/sch_generic.h
net/core/dev.c
net/sched/sch_atm.c
net/sched/sch_blackhole.c
net/sched/sch_cake.c
net/sched/sch_cbq.c
net/sched/sch_cbs.c
net/sched/sch_choke.c
net/sched/sch_codel.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_etf.c
net/sched/sch_ets.c
net/sched/sch_fifo.c
net/sched/sch_fq.c
net/sched/sch_fq_codel.c
net/sched/sch_fq_pie.c
net/sched/sch_generic.c
net/sched/sch_gred.c
net/sched/sch_hfsc.c
net/sched/sch_hhf.c
net/sched/sch_htb.c
net/sched/sch_multiq.c
net/sched/sch_netem.c
net/sched/sch_pie.c
net/sched/sch_plug.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_red.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c
net/sched/sch_skbprio.c
net/sched/sch_taprio.c
net/sched/sch_tbf.c
net/sched/sch_teql.c

index c510b03b97513d6be0447c74c44d029d838781b0..fceb3d63c9256bbcc985d8cf352ee810f0c6fa55 100644 (file)
@@ -57,6 +57,7 @@ struct qdisc_skb_head {
 struct Qdisc {
        int                     (*enqueue)(struct sk_buff *skb,
                                           struct Qdisc *sch,
+                                          spinlock_t *root_lock,
                                           struct sk_buff **to_free);
        struct sk_buff *        (*dequeue)(struct Qdisc *sch);
        unsigned int            flags;
@@ -241,6 +242,7 @@ struct Qdisc_ops {
 
        int                     (*enqueue)(struct sk_buff *skb,
                                           struct Qdisc *sch,
+                                          spinlock_t *root_lock,
                                           struct sk_buff **to_free);
        struct sk_buff *        (*dequeue)(struct Qdisc *);
        struct sk_buff *        (*peek)(struct Qdisc *);
@@ -788,11 +790,11 @@ static inline void qdisc_calculate_pkt_len(struct sk_buff *skb,
 #endif
 }
 
-static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                                struct sk_buff **to_free)
 {
        qdisc_calculate_pkt_len(skb, sch);
-       return sch->enqueue(skb, sch, to_free);
+       return sch->enqueue(skb, sch, root_lock, to_free);
 }
 
 static inline void _bstats_update(struct gnet_stats_basic_packed *bstats,
index 3a46b86cbd67f00f4fc9be281bff35745cf675cd..c02bae9278122d47b30e99f3c5aafbfe1a6f0aec 100644 (file)
@@ -3749,7 +3749,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
        qdisc_calculate_pkt_len(skb, q);
 
        if (q->flags & TCQ_F_NOLOCK) {
-               rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
+               rc = q->enqueue(skb, q, NULL, &to_free) & NET_XMIT_MASK;
                qdisc_run(q);
 
                if (unlikely(to_free))
@@ -3792,7 +3792,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
                qdisc_run_end(q);
                rc = NET_XMIT_SUCCESS;
        } else {
-               rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
+               rc = q->enqueue(skb, q, root_lock, &to_free) & NET_XMIT_MASK;
                if (qdisc_run_begin(q)) {
                        if (unlikely(contended)) {
                                spin_unlock(&q->busylock);
index ee12ca9f55b4fd59a6c0b826ad961ac3984c3ba2..fb6b16c4e46d6a5c1e19004fceead1c598818369 100644 (file)
@@ -374,7 +374,7 @@ static struct tcf_block *atm_tc_tcf_block(struct Qdisc *sch, unsigned long cl,
 
 /* --------------------------- Qdisc operations ---------------------------- */
 
-static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                          struct sk_buff **to_free)
 {
        struct atm_qdisc_data *p = qdisc_priv(sch);
@@ -432,7 +432,7 @@ done:
 #endif
        }
 
-       ret = qdisc_enqueue(skb, flow->q, to_free);
+       ret = qdisc_enqueue(skb, flow->q, root_lock, to_free);
        if (ret != NET_XMIT_SUCCESS) {
 drop: __maybe_unused
                if (net_xmit_drop_count(ret)) {
index a7f7667ae9849ae17fdfe5644b4ae463d40ec7ba..187644657c4f9d71a7884005638d41d95d5cd404 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 
-static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                             struct sk_buff **to_free)
 {
        qdisc_drop(skb, sch, to_free);
index 65a95cb094e8b65c963bb6ce1ad5f164db7940a5..e9c502dd29a27604eb0b37d1a3412228f75ef1e9 100644 (file)
@@ -1687,7 +1687,7 @@ hash:
 
 static void cake_reconfigure(struct Qdisc *sch);
 
-static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                        struct sk_buff **to_free)
 {
        struct cake_sched_data *q = qdisc_priv(sch);
index 39b427dc751282db7adb2d0803eecccb0457c316..052d4a1af69a4fb9f9480e53fc8190aed6f667f6 100644 (file)
@@ -356,7 +356,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
 }
 
 static int
-cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
            struct sk_buff **to_free)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
@@ -373,7 +373,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return ret;
        }
 
-       ret = qdisc_enqueue(skb, cl->q, to_free);
+       ret = qdisc_enqueue(skb, cl->q, root_lock, to_free);
        if (ret == NET_XMIT_SUCCESS) {
                sch->q.qlen++;
                cbq_mark_toplevel(q, cl);
index 2eaac2ff380fafaf9dbaeade2b86e029bddceecc..7af15ebe07f78b21715c7d57cbd69119494bae3c 100644 (file)
@@ -77,7 +77,7 @@ struct cbs_sched_data {
        s64 sendslope; /* in bytes/s */
        s64 idleslope; /* in bytes/s */
        struct qdisc_watchdog watchdog;
-       int (*enqueue)(struct sk_buff *skb, struct Qdisc *sch,
+       int (*enqueue)(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free);
        struct sk_buff *(*dequeue)(struct Qdisc *sch);
        struct Qdisc *qdisc;
@@ -85,13 +85,13 @@ struct cbs_sched_data {
 };
 
 static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
-                            struct Qdisc *child,
+                            struct Qdisc *child, spinlock_t *root_lock,
                             struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
        int err;
 
-       err = child->ops->enqueue(skb, child, to_free);
+       err = child->ops->enqueue(skb, child, root_lock, to_free);
        if (err != NET_XMIT_SUCCESS)
                return err;
 
@@ -101,16 +101,16 @@ static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        return NET_XMIT_SUCCESS;
 }
 
-static int cbs_enqueue_offload(struct sk_buff *skb, struct Qdisc *sch,
+static int cbs_enqueue_offload(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                               struct sk_buff **to_free)
 {
        struct cbs_sched_data *q = qdisc_priv(sch);
        struct Qdisc *qdisc = q->qdisc;
 
-       return cbs_child_enqueue(skb, sch, qdisc, to_free);
+       return cbs_child_enqueue(skb, sch, qdisc, root_lock, to_free);
 }
 
-static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch,
+static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                            struct sk_buff **to_free)
 {
        struct cbs_sched_data *q = qdisc_priv(sch);
@@ -124,15 +124,15 @@ static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch,
                q->last = ktime_get_ns();
        }
 
-       return cbs_child_enqueue(skb, sch, qdisc, to_free);
+       return cbs_child_enqueue(skb, sch, qdisc, root_lock, to_free);
 }
 
-static int cbs_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int cbs_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        struct cbs_sched_data *q = qdisc_priv(sch);
 
-       return q->enqueue(skb, sch, to_free);
+       return q->enqueue(skb, sch, root_lock, to_free);
 }
 
 /* timediff is in ns, slope is in bytes/s */
index bd618b00d3193242b1a166b5c48b3bccbcef5d2e..baf3faee31aacbb2b07fdf4f2e7d4a782b82aeef 100644 (file)
@@ -210,7 +210,7 @@ static bool choke_match_random(const struct choke_sched_data *q,
        return choke_match_flow(oskb, nskb);
 }
 
-static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                         struct sk_buff **to_free)
 {
        struct choke_sched_data *q = qdisc_priv(sch);
index 30169b3adbbb064c51b6006755d56446570f974c..1d94837abdd83004352d7574eccb172e006c9ab1 100644 (file)
@@ -108,7 +108,7 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
        return skb;
 }
 
-static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                               struct sk_buff **to_free)
 {
        struct codel_sched_data *q;
index 07a2b0b354954f4874883f486c8b855a17c4be06..0d5c9a8ec61dab0f9fa66775bd9e0cfbd4c82b23 100644 (file)
@@ -337,7 +337,7 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
        return NULL;
 }
 
-static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
@@ -355,7 +355,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 
        first = !cl->qdisc->q.qlen;
-       err = qdisc_enqueue(skb, cl->qdisc, to_free);
+       err = qdisc_enqueue(skb, cl->qdisc, root_lock, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
                        cl->qstats.drops++;
index 05605b30bef3abac1da2e0e821c871a54b3635ba..fbe49fffcdbb3b1d035913bb6120f97750cf74ec 100644 (file)
@@ -198,7 +198,7 @@ static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
 
 /* --------------------------- Qdisc operations ---------------------------- */
 
-static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                          struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
@@ -267,7 +267,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                }
        }
 
-       err = qdisc_enqueue(skb, p->q, to_free);
+       err = qdisc_enqueue(skb, p->q, root_lock, to_free);
        if (err != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(err))
                        qdisc_qstats_drop(sch);
index c48f91075b5c60ee4fe9e10186c913baf5894a69..7a7c50a6811540c6a354312fb5e05d22bd590672 100644 (file)
@@ -160,7 +160,7 @@ static void report_sock_error(struct sk_buff *skb, u32 err, u8 code)
 }
 
 static int etf_enqueue_timesortedlist(struct sk_buff *nskb, struct Qdisc *sch,
-                                     struct sk_buff **to_free)
+                                     spinlock_t *root_lock, struct sk_buff **to_free)
 {
        struct etf_sched_data *q = qdisc_priv(sch);
        struct rb_node **p = &q->head.rb_root.rb_node, *parent = NULL;
index a87e9159338c48271d8a2eaee0253721dd48d180..373dc5855d4e81a76c0c9b6cb81a338d6588d1de 100644 (file)
@@ -415,7 +415,7 @@ static struct ets_class *ets_classify(struct sk_buff *skb, struct Qdisc *sch,
        return &q->classes[band];
 }
 
-static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                             struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
@@ -433,7 +433,7 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 
        first = !cl->qdisc->q.qlen;
-       err = qdisc_enqueue(skb, cl->qdisc, to_free);
+       err = qdisc_enqueue(skb, cl->qdisc, root_lock, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
                        cl->qstats.drops++;
index a579a4131d22d771c9766f5ad6cdb16ece3034c0..b4da5b624ad866a0d924a00da520195f0df23ad9 100644 (file)
@@ -16,7 +16,7 @@
 
 /* 1 band FIFO pseudo-"scheduler" */
 
-static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                         struct sk_buff **to_free)
 {
        if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= sch->limit))
@@ -25,7 +25,7 @@ static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        return qdisc_drop(skb, sch, to_free);
 }
 
-static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                         struct sk_buff **to_free)
 {
        if (likely(sch->q.qlen < sch->limit))
@@ -34,7 +34,7 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        return qdisc_drop(skb, sch, to_free);
 }
 
-static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                              struct sk_buff **to_free)
 {
        unsigned int prev_backlog;
index 2fb76fc0cc31bf732e0b32a95d8e45f457acb683..a90d745c41e05d529ebb1f7f6579f939b7ff2513 100644 (file)
@@ -439,7 +439,7 @@ static bool fq_packet_beyond_horizon(const struct sk_buff *skb,
        return unlikely((s64)skb->tstamp > (s64)(q->ktime_cache + q->horizon));
 }
 
-static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                      struct sk_buff **to_free)
 {
        struct fq_sched_data *q = qdisc_priv(sch);
index 459a784056c0f30db8025320469a4ea5cd4ad592..6bf979f955091731da639ca7fbe241b2e76d61ee 100644 (file)
@@ -181,7 +181,7 @@ static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets,
        return idx;
 }
 
-static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                            struct sk_buff **to_free)
 {
        struct fq_codel_sched_data *q = qdisc_priv(sch);
index fb760cee824e4cb1807651346d333e2d4590a663..a27a250ab8f9a88e02672be30fa1a59236121d7a 100644 (file)
@@ -125,7 +125,7 @@ static inline void flow_queue_add(struct fq_pie_flow *flow,
        skb->next = NULL;
 }
 
-static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                                struct sk_buff **to_free)
 {
        struct fq_pie_sched_data *q = qdisc_priv(sch);
index 265a61d011dfaa7ec0f8fb8aaede920784f690c9..715cde1df9e460de0d549b2b91c8feba81952f0f 100644 (file)
@@ -520,7 +520,7 @@ EXPORT_SYMBOL(netif_carrier_off);
    cheaper.
  */
 
-static int noop_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
+static int noop_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, spinlock_t *root_lock,
                        struct sk_buff **to_free)
 {
        __qdisc_drop(skb, to_free);
@@ -614,7 +614,7 @@ static inline struct skb_array *band2list(struct pfifo_fast_priv *priv,
        return &priv->q[band];
 }
 
-static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
+static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, spinlock_t *root_lock,
                              struct sk_buff **to_free)
 {
        int band = prio2band[skb->priority & TC_PRIO_MAX];
index 8599c6f31b057f494f64941929a2012e5fddac5a..7d67c6cd6605b8aad70416e6bbf1e990c5b10059 100644 (file)
@@ -161,7 +161,7 @@ static bool gred_per_vq_red_flags_used(struct gred_sched *table)
        return false;
 }
 
-static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                        struct sk_buff **to_free)
 {
        struct gred_sched_data *q = NULL;
index 433f2190960fe88235a5c6381760596cfc93305a..7f6670044f0a917a487d7ac94a2fc756fd673a0e 100644 (file)
@@ -1528,8 +1528,8 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
        return -1;
 }
 
-static int
-hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
+static int hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
+                       struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
        struct hfsc_class *cl;
@@ -1545,7 +1545,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
        }
 
        first = !cl->qdisc->q.qlen;
-       err = qdisc_enqueue(skb, cl->qdisc, to_free);
+       err = qdisc_enqueue(skb, cl->qdisc, root_lock, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
                        cl->qstats.drops++;
index 420ede8753229faae172c0829b60d81e8eaa8de8..ddc6bf1d85d0e146107afa99a5fd25a0b5988556 100644 (file)
@@ -368,7 +368,7 @@ static unsigned int hhf_drop(struct Qdisc *sch, struct sk_buff **to_free)
        return bucket - q->buckets;
 }
 
-static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        struct hhf_sched_data *q = qdisc_priv(sch);
index 8184c87da8bec7d93ac29d2c8c4259ad79e9f1c4..52fc513688b1b127c7018d9c949920524dc6f654 100644 (file)
@@ -576,7 +576,7 @@ static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
        cl->prio_activity = 0;
 }
 
-static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        int uninitialized_var(ret);
@@ -599,7 +599,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                __qdisc_drop(skb, to_free);
                return ret;
 #endif
-       } else if ((ret = qdisc_enqueue(skb, cl->leaf.q,
+       } else if ((ret = qdisc_enqueue(skb, cl->leaf.q, root_lock,
                                        to_free)) != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret)) {
                        qdisc_qstats_drop(sch);
index 1330ad2249317ccfdb81777c5ac4c56f3f500a64..648611f5c10523626727317d5fd96f3411aef989 100644 (file)
@@ -57,7 +57,7 @@ multiq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 }
 
 static int
-multiq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+multiq_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
               struct sk_buff **to_free)
 {
        struct Qdisc *qdisc;
@@ -74,7 +74,7 @@ multiq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 #endif
 
-       ret = qdisc_enqueue(skb, qdisc, to_free);
+       ret = qdisc_enqueue(skb, qdisc, root_lock, to_free);
        if (ret == NET_XMIT_SUCCESS) {
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
index 84f82771cdf5dce6552bd790242a8c0b8b320e06..8fb17483a34f3499b219ec95b422922f8fdb3a5d 100644 (file)
@@ -431,7 +431,7 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
  *     NET_XMIT_DROP: queue length didn't change.
  *      NET_XMIT_SUCCESS: one skb was queued.
  */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                         struct sk_buff **to_free)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
@@ -480,7 +480,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
 
                q->duplicate = 0;
-               rootq->enqueue(skb2, rootq, to_free);
+               rootq->enqueue(skb2, rootq, root_lock, to_free);
                q->duplicate = dupsave;
                rc_drop = NET_XMIT_SUCCESS;
        }
@@ -604,7 +604,7 @@ finish_segs:
                        skb_mark_not_on_list(segs);
                        qdisc_skb_cb(segs)->pkt_len = segs->len;
                        last_len = segs->len;
-                       rc = qdisc_enqueue(segs, sch, to_free);
+                       rc = qdisc_enqueue(segs, sch, root_lock, to_free);
                        if (rc != NET_XMIT_SUCCESS) {
                                if (net_xmit_drop_count(rc))
                                        qdisc_qstats_drop(sch);
@@ -720,7 +720,7 @@ deliver:
                                struct sk_buff *to_free = NULL;
                                int err;
 
-                               err = qdisc_enqueue(skb, q->qdisc, &to_free);
+                               err = qdisc_enqueue(skb, q->qdisc, NULL, &to_free);
                                kfree_skb_list(to_free);
                                if (err != NET_XMIT_SUCCESS &&
                                    net_xmit_drop_count(err)) {
index c65077f0c0f39832ee97f4e89f25639306b19281..b305313b64e30b2ce595fa2453610917d764747a 100644 (file)
@@ -82,7 +82,7 @@ bool pie_drop_early(struct Qdisc *sch, struct pie_params *params,
 }
 EXPORT_SYMBOL_GPL(pie_drop_early);
 
-static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                             struct sk_buff **to_free)
 {
        struct pie_sched_data *q = qdisc_priv(sch);
index cbc2ebca4548c927070dd2dbd7685cdb6a7ffe8f..e5f8b4769b4d60c5347a5744da7d750de4cfed2e 100644 (file)
@@ -84,7 +84,7 @@ struct plug_sched_data {
        u32 pkts_to_release;
 };
 
-static int plug_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int plug_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                        struct sk_buff **to_free)
 {
        struct plug_sched_data *q = qdisc_priv(sch);
index 647941702f9fcaa47242382c8489a8ee179064f4..a3e187f2603c0eeef0200227571e33fe6feb824e 100644 (file)
@@ -65,8 +65,8 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        return q->queues[band];
 }
 
-static int
-prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
+static int prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
+                       struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb);
        struct Qdisc *qdisc;
@@ -83,7 +83,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
        }
 #endif
 
-       ret = qdisc_enqueue(skb, qdisc, to_free);
+       ret = qdisc_enqueue(skb, qdisc, root_lock, to_free);
        if (ret == NET_XMIT_SUCCESS) {
                sch->qstats.backlog += len;
                sch->q.qlen++;
index 0b05ac7c848eba8bc672607d2cfeb3e302ceea5b..ede854516825c6dc84e222a96e6cf72f33eb88a2 100644 (file)
@@ -1194,7 +1194,7 @@ static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
        return agg;
 }
 
-static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        unsigned int len = qdisc_pkt_len(skb), gso_segs;
@@ -1225,7 +1225,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
        gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
        first = !cl->qdisc->q.qlen;
-       err = qdisc_enqueue(skb, cl->qdisc, to_free);
+       err = qdisc_enqueue(skb, cl->qdisc, root_lock, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
                if (net_xmit_drop_count(err)) {
index 555a1b9e467fc5f5cbd28944510c7dfd4527637d..6ace7d757e8b4ab6c4df6e691e841689ef1df5d2 100644 (file)
@@ -65,7 +65,7 @@ static int red_use_nodrop(struct red_sched_data *q)
        return q->flags & TC_RED_NODROP;
 }
 
-static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        struct red_sched_data *q = qdisc_priv(sch);
@@ -118,7 +118,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                break;
        }
 
-       ret = qdisc_enqueue(skb, child, to_free);
+       ret = qdisc_enqueue(skb, child, root_lock, to_free);
        if (likely(ret == NET_XMIT_SUCCESS)) {
                qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
index 4074c50ac3d73100dd82bd631c127326ff49f355..d2a6e78262bbcea648a0393ed3dde37cd9f77fcc 100644 (file)
@@ -276,7 +276,7 @@ static bool sfb_classify(struct sk_buff *skb, struct tcf_proto *fl,
        return false;
 }
 
-static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
 
@@ -399,7 +399,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 
 enqueue:
-       ret = qdisc_enqueue(skb, child, to_free);
+       ret = qdisc_enqueue(skb, child, root_lock, to_free);
        if (likely(ret == NET_XMIT_SUCCESS)) {
                qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
index 5a6def5e4e6df2e7b66c88aa877c7318270d48be..46cdefd69e44dd4cfcd96082d967977171632406 100644 (file)
@@ -343,7 +343,7 @@ static int sfq_headdrop(const struct sfq_sched_data *q)
 }
 
 static int
-sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
+sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock, struct sk_buff **to_free)
 {
        struct sfq_sched_data *q = qdisc_priv(sch);
        unsigned int hash, dropped;
index 7a5e4c454715617cb57c6db7de7fdaa9e6886d40..f75f237c44369316fee6c8bfc7c4ee91a44756e9 100644 (file)
@@ -65,7 +65,7 @@ static u16 calc_new_low_prio(const struct skbprio_sched_data *q)
        return SKBPRIO_MAX_PRIORITY - 1;
 }
 
-static int skbprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int skbprio_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                          struct sk_buff **to_free)
 {
        const unsigned int max_priority = SKBPRIO_MAX_PRIORITY - 1;
index e981992634ddfe9373fe19d4915615bf5c334691..daef2ff60a985e7ad6577a239715f20eb7faefa3 100644 (file)
@@ -410,7 +410,7 @@ done:
        return txtime;
 }
 
-static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                          struct sk_buff **to_free)
 {
        struct taprio_sched *q = qdisc_priv(sch);
@@ -435,7 +435,7 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
 
-       return qdisc_enqueue(skb, child, to_free);
+       return qdisc_enqueue(skb, child, root_lock, to_free);
 }
 
 static struct sk_buff *taprio_peek_soft(struct Qdisc *sch)
index 78e79029dc631a8b0a9985ea23b1568b30e10f96..c3eb5cdb83a82a38048e8e9126ae108d029d20ef 100644 (file)
@@ -187,7 +187,7 @@ static int tbf_offload_dump(struct Qdisc *sch)
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
-static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
+static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
@@ -206,7 +206,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
                skb_mark_not_on_list(segs);
                qdisc_skb_cb(segs)->pkt_len = segs->len;
                len += segs->len;
-               ret = qdisc_enqueue(segs, q->qdisc, to_free);
+               ret = qdisc_enqueue(segs, q->qdisc, root_lock, to_free);
                if (ret != NET_XMIT_SUCCESS) {
                        if (net_xmit_drop_count(ret))
                                qdisc_qstats_drop(sch);
@@ -221,7 +221,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
        return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
 }
 
-static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
                       struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
@@ -231,10 +231,10 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (qdisc_pkt_len(skb) > q->max_size) {
                if (skb_is_gso(skb) &&
                    skb_gso_validate_mac_len(skb, q->max_size))
-                       return tbf_segment(skb, sch, to_free);
+                       return tbf_segment(skb, sch, root_lock, to_free);
                return qdisc_drop(skb, sch, to_free);
        }
-       ret = qdisc_enqueue(skb, q->qdisc, to_free);
+       ret = qdisc_enqueue(skb, q->qdisc, root_lock, to_free);
        if (ret != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret))
                        qdisc_qstats_drop(sch);
index 689ef6f3ded80968a46aaccc9dc6fd4db9506a85..51196465347616f0fb949109277f954fa5a77f19 100644 (file)
@@ -72,8 +72,8 @@ struct teql_sched_data {
 
 /* "teql*" qdisc routines */
 
-static int
-teql_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
+static int teql_enqueue(struct sk_buff *skb, struct Qdisc *sch, spinlock_t *root_lock,
+                       struct sk_buff **to_free)
 {
        struct net_device *dev = qdisc_dev(sch);
        struct teql_sched_data *q = qdisc_priv(sch);