Skip to content

Commit 9594665

Browse files
koct9idavem330
authored andcommitted
net_sched: call qlen_notify only if child qdisc is empty
This callback is used for deactivating class in parent qdisc. This is cheaper to test queue length right here. Also this allows to catch draining screwed backlog and prevent second deactivation of already inactive parent class which will crash kernel for sure. Kernel with print warning at destruction of child qdisc where no packets but backlog is not zero. Signed-off-by: Konstantin Khlebnikov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 869cec9 commit 9594665

File tree

6 files changed

+15
-13
lines changed

6 files changed

+15
-13
lines changed

net/sched/sch_api.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
749749
const struct Qdisc_class_ops *cops;
750750
unsigned long cl;
751751
u32 parentid;
752+
bool notify;
752753
int drops;
753754

754755
if (n == 0 && len == 0)
@@ -761,14 +762,21 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
761762

762763
if (sch->flags & TCQ_F_NOPARENT)
763764
break;
765+
/* Notify parent qdisc only if child qdisc becomes empty.
766+
*
767+
* If child was empty even before update then backlog
768+
* counter is screwed and we skip notification because
769+
* parent class is already passive.
770+
*/
771+
notify = !sch->q.qlen && !WARN_ON_ONCE(!n);
764772
/* TODO: perform the search on a per txq basis */
765773
sch = qdisc_lookup(qdisc_dev(sch), TC_H_MAJ(parentid));
766774
if (sch == NULL) {
767775
WARN_ON_ONCE(parentid != TC_H_ROOT);
768776
break;
769777
}
770778
cops = sch->ops->cl_ops;
771-
if (cops->qlen_notify) {
779+
if (notify && cops->qlen_notify) {
772780
cl = cops->get(sch, parentid);
773781
cops->qlen_notify(sch, cl);
774782
cops->put(sch, cl);

net/sched/sch_cbq.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,8 +1385,7 @@ static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
13851385
{
13861386
struct cbq_class *cl = (struct cbq_class *)arg;
13871387

1388-
if (cl->q->q.qlen == 0)
1389-
cbq_deactivate_class(cl);
1388+
cbq_deactivate_class(cl);
13901389
}
13911390

13921391
static unsigned long cbq_get(struct Qdisc *sch, u32 classid)

net/sched/sch_drr.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,7 @@ static void drr_qlen_notify(struct Qdisc *csh, unsigned long arg)
246246
{
247247
struct drr_class *cl = (struct drr_class *)arg;
248248

249-
if (cl->qdisc->q.qlen == 0)
250-
list_del(&cl->alist);
249+
list_del(&cl->alist);
251250
}
252251

253252
static int drr_dump_class(struct Qdisc *sch, unsigned long arg,

net/sched/sch_hfsc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,10 +1221,8 @@ hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
12211221
{
12221222
struct hfsc_class *cl = (struct hfsc_class *)arg;
12231223

1224-
if (cl->qdisc->q.qlen == 0) {
1225-
update_vf(cl, 0, 0);
1226-
set_passive(cl);
1227-
}
1224+
update_vf(cl, 0, 0);
1225+
set_passive(cl);
12281226
}
12291227

12301228
static unsigned long

net/sched/sch_htb.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,8 +1186,7 @@ static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
11861186
{
11871187
struct htb_class *cl = (struct htb_class *)arg;
11881188

1189-
if (cl->un.leaf.q->q.qlen == 0)
1190-
htb_deactivate(qdisc_priv(sch), cl);
1189+
htb_deactivate(qdisc_priv(sch), cl);
11911190
}
11921191

11931192
static unsigned long htb_get(struct Qdisc *sch, u32 classid)

net/sched/sch_qfq.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,8 +1428,7 @@ static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
14281428
struct qfq_sched *q = qdisc_priv(sch);
14291429
struct qfq_class *cl = (struct qfq_class *)arg;
14301430

1431-
if (cl->qdisc->q.qlen == 0)
1432-
qfq_deactivate_class(q, cl);
1431+
qfq_deactivate_class(q, cl);
14331432
}
14341433

14351434
static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)

0 commit comments

Comments
 (0)