diff options
author | Patrick McHardy <kaber@trash.net> | 2008-11-24 18:46:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-24 18:46:08 -0500 |
commit | 3f0947c3ffaed33c1c38b79e4b17f75ba072d3e9 (patch) | |
tree | aabc1d3fadbfbfb97b2fe56884fad70197e50d47 /net/sched | |
parent | 4b40eed73e3787d60160beed1352ceadd24f6be1 (diff) |
pkt_sched: sch_drr: fix drr_dequeue loop()
Jarek Poplawski points out:
If all child qdiscs of sch_drr are non-work-conserving (e.g. sch_tbf)
drr_dequeue() will busy-loop waiting for skbs instead of leaving the
job for a watchdog. Checking for list_empty() in each loop isn't
necessary either, because this can never be true except the first time.
Using non-work-conserving qdiscs as children of DRR makes no sense,
simply bail out in that case.
Reported-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_drr.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 37e6ab99bbea..e7a7e87b141a 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -373,11 +373,13 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) | |||
373 | struct sk_buff *skb; | 373 | struct sk_buff *skb; |
374 | unsigned int len; | 374 | unsigned int len; |
375 | 375 | ||
376 | while (!list_empty(&q->active)) { | 376 | if (list_empty(&q->active)) |
377 | goto out; | ||
378 | while (1) { | ||
377 | cl = list_first_entry(&q->active, struct drr_class, alist); | 379 | cl = list_first_entry(&q->active, struct drr_class, alist); |
378 | skb = cl->qdisc->ops->peek(cl->qdisc); | 380 | skb = cl->qdisc->ops->peek(cl->qdisc); |
379 | if (skb == NULL) | 381 | if (skb == NULL) |
380 | goto skip; | 382 | goto out; |
381 | 383 | ||
382 | len = qdisc_pkt_len(skb); | 384 | len = qdisc_pkt_len(skb); |
383 | if (len <= cl->deficit) { | 385 | if (len <= cl->deficit) { |
@@ -390,9 +392,9 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) | |||
390 | } | 392 | } |
391 | 393 | ||
392 | cl->deficit += cl->quantum; | 394 | cl->deficit += cl->quantum; |
393 | skip: | ||
394 | list_move_tail(&cl->alist, &q->active); | 395 | list_move_tail(&cl->alist, &q->active); |
395 | } | 396 | } |
397 | out: | ||
396 | return NULL; | 398 | return NULL; |
397 | } | 399 | } |
398 | 400 | ||