Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 3075

kernel-2.6.18-238.el5.src.rpm

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) {