Skip to content

Commit 8a53e61

Browse files
Paolo Abenidavem330
authored andcommitted
net: sched: when clearing NOLOCK, clear TCQ_F_CPUSTATS, too
Since stats updating is always consistent with TCQ_F_CPUSTATS flag, we can disable it at qdisc creation time flipping such bit. In my experiments, if the NOLOCK flag is cleared, per CPU stats accounting does not give any measurable performance gain, but it waste some memory. Let's clear TCQ_F_CPUSTATS together with NOLOCK, when enslaving a NOLOCK qdisc to 'lock' one. Use stats update helper inside pfifo_fast, to cope correctly with TCQ_F_CPUSTATS flag change. As a side effect, q.qlen value for any child qdiscs is always consistent for all lock classfull qdiscs. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9c01c9f commit 8a53e61

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

include/net/sch_generic.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,32 @@ static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
11061106
return skb;
11071107
}
11081108

1109+
static inline void qdisc_update_stats_at_dequeue(struct Qdisc *sch,
1110+
struct sk_buff *skb)
1111+
{
1112+
if (qdisc_is_percpu_stats(sch)) {
1113+
qdisc_qstats_cpu_backlog_dec(sch, skb);
1114+
qdisc_bstats_cpu_update(sch, skb);
1115+
qdisc_qstats_atomic_qlen_dec(sch);
1116+
} else {
1117+
qdisc_qstats_backlog_dec(sch, skb);
1118+
qdisc_bstats_update(sch, skb);
1119+
sch->q.qlen--;
1120+
}
1121+
}
1122+
1123+
static inline void qdisc_update_stats_at_enqueue(struct Qdisc *sch,
1124+
unsigned int pkt_len)
1125+
{
1126+
if (qdisc_is_percpu_stats(sch)) {
1127+
qdisc_qstats_atomic_qlen_inc(sch);
1128+
this_cpu_add(sch->cpu_qstats->backlog, pkt_len);
1129+
} else {
1130+
sch->qstats.backlog += pkt_len;
1131+
sch->q.qlen++;
1132+
}
1133+
}
1134+
11091135
/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */
11101136
static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
11111137
{

net/sched/sch_api.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,19 @@ static void notify_and_destroy(struct net *net, struct sk_buff *skb,
998998
qdisc_put(old);
999999
}
10001000

1001+
static void qdisc_clear_nolock(struct Qdisc *sch)
1002+
{
1003+
sch->flags &= ~TCQ_F_NOLOCK;
1004+
if (!(sch->flags & TCQ_F_CPUSTATS))
1005+
return;
1006+
1007+
free_percpu(sch->cpu_bstats);
1008+
free_percpu(sch->cpu_qstats);
1009+
sch->cpu_bstats = NULL;
1010+
sch->cpu_qstats = NULL;
1011+
sch->flags &= ~TCQ_F_CPUSTATS;
1012+
}
1013+
10011014
/* Graft qdisc "new" to class "classid" of qdisc "parent" or
10021015
* to device "dev".
10031016
*
@@ -1076,7 +1089,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
10761089
/* Only support running class lockless if parent is lockless */
10771090
if (new && (new->flags & TCQ_F_NOLOCK) &&
10781091
parent && !(parent->flags & TCQ_F_NOLOCK))
1079-
new->flags &= ~TCQ_F_NOLOCK;
1092+
qdisc_clear_nolock(new);
10801093

10811094
if (!cops || !cops->graft)
10821095
return -EOPNOTSUPP;

net/sched/sch_generic.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -629,11 +629,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
629629
if (unlikely(err))
630630
return qdisc_drop_cpu(skb, qdisc, to_free);
631631

632-
qdisc_qstats_atomic_qlen_inc(qdisc);
633-
/* Note: skb can not be used after skb_array_produce(),
634-
* so we better not use qdisc_qstats_cpu_backlog_inc()
635-
*/
636-
this_cpu_add(qdisc->cpu_qstats->backlog, pkt_len);
632+
qdisc_update_stats_at_enqueue(qdisc, pkt_len);
637633
return NET_XMIT_SUCCESS;
638634
}
639635

@@ -652,9 +648,7 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
652648
skb = __skb_array_consume(q);
653649
}
654650
if (likely(skb)) {
655-
qdisc_qstats_cpu_backlog_dec(qdisc, skb);
656-
qdisc_bstats_cpu_update(qdisc, skb);
657-
qdisc_qstats_atomic_qlen_dec(qdisc);
651+
qdisc_update_stats_at_dequeue(qdisc, skb);
658652
} else {
659653
qdisc->empty = true;
660654
}

0 commit comments

Comments
 (0)