aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_fq.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_fq.c')
-rw-r--r--net/sched/sch_fq.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 08ef7a42c0e4..21e251766eb1 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -601,6 +601,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
601{ 601{
602 struct fq_sched_data *q = qdisc_priv(sch); 602 struct fq_sched_data *q = qdisc_priv(sch);
603 struct rb_root *array; 603 struct rb_root *array;
604 void *old_fq_root;
604 u32 idx; 605 u32 idx;
605 606
606 if (q->fq_root && log == q->fq_trees_log) 607 if (q->fq_root && log == q->fq_trees_log)
@@ -615,13 +616,19 @@ static int fq_resize(struct Qdisc *sch, u32 log)
615 for (idx = 0; idx < (1U << log); idx++) 616 for (idx = 0; idx < (1U << log); idx++)
616 array[idx] = RB_ROOT; 617 array[idx] = RB_ROOT;
617 618
618 if (q->fq_root) { 619 sch_tree_lock(sch);
619 fq_rehash(q, q->fq_root, q->fq_trees_log, array, log); 620
620 fq_free(q->fq_root); 621 old_fq_root = q->fq_root;
621 } 622 if (old_fq_root)
623 fq_rehash(q, old_fq_root, q->fq_trees_log, array, log);
624
622 q->fq_root = array; 625 q->fq_root = array;
623 q->fq_trees_log = log; 626 q->fq_trees_log = log;
624 627
628 sch_tree_unlock(sch);
629
630 fq_free(old_fq_root);
631
625 return 0; 632 return 0;
626} 633}
627 634
@@ -697,9 +704,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
697 q->flow_refill_delay = usecs_to_jiffies(usecs_delay); 704 q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
698 } 705 }
699 706
700 if (!err) 707 if (!err) {
708 sch_tree_unlock(sch);
701 err = fq_resize(sch, fq_log); 709 err = fq_resize(sch, fq_log);
702 710 sch_tree_lock(sch);
711 }
703 while (sch->q.qlen > sch->limit) { 712 while (sch->q.qlen > sch->limit) {
704 struct sk_buff *skb = fq_dequeue(sch); 713 struct sk_buff *skb = fq_dequeue(sch);
705 714