From: Jiri Pirko <jpirko@redhat.com> Date: Thu, 29 Apr 2010 11:27:26 -0400 Subject: [net] sched: fix SFQ qdisc crash w/limit of 2 packets Message-id: <20100429112725.GB4034@psychotron.lab.eng.brq.redhat.com> Patchwork-id: 24694 O-Subject: [RHEL5.6 patch] BZ579774 net: [PKT_SCHED]: Fix 'SFQ qdisc crashes with limit of 2 packets' Bugzilla: 579774 RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Jiri Olsa <jolsa@redhat.com> RH-Acked-by: Dean Nelson <dnelson@redhat.com> BZ579774 https://bugzilla.redhat.com/show_bug.cgi?id=579774 Description: After adding SFQ qdisc with limit of 2 packets, kernel crashes when packets are transmitted. This patch fixes the issue. Upstream: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=5588b40d7c2bff75ee573ed42d1738c73ce24492 Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=2408923 Tested on x86_64. Works as expected. Jirka Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index d0d6e59..e939d55 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -281,7 +281,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen < q->limit-1) { + if (++sch->q.qlen <= q->limit) { sch->bstats.bytes += skb->len; sch->bstats.packets++; return 0; @@ -317,7 +317,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen < q->limit - 1) { + if (++sch->q.qlen <= q->limit) { sch->qstats.requeues++; return 0; } @@ -401,9 +401,9 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) - q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); + q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2); - while (sch->q.qlen >= q->limit-1) + while (sch->q.qlen > q->limit) sfq_drop(sch); del_timer(&q->perturb_timer); @@ -431,7 +431,7 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; } - q->limit = SFQ_DEPTH; + q->limit = SFQ_DEPTH - 2; q->max_depth = 0; q->tail = SFQ_DEPTH; if (opt == NULL) {