Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net_sched: sch_fq: rework fq_gc() to avoid stack canary

Using kmem_cache_free_bulk() in fq_gc() was not optimal.

1) It needs an array.
2) It is only saving cpu cycles for large batches.

The automatic array forces a stack canary, which is expensive.

In practice fq_gc was finding zero, one or two flows at most
per round.

Remove the array, use kmem_cache_free().

This makes fq_enqueue() smaller and faster.

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-79 (-79)
Function old new delta
fq_enqueue 1629 1550 -79
Total: Before=24886583, After=24886504, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260204190034.76277-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
2214aab2 7acee67a

+11 -13
+11 -13
net/sched/sch_fq.c
··· 245 245 static struct kmem_cache *fq_flow_cachep __read_mostly; 246 246 247 247 248 - /* limit number of collected flows per round */ 249 - #define FQ_GC_MAX 8 250 248 #define FQ_GC_AGE (3*HZ) 251 249 252 250 static bool fq_gc_candidate(const struct fq_flow *f) ··· 257 259 struct rb_root *root, 258 260 struct sock *sk) 259 261 { 262 + struct fq_flow *f, *tofree = NULL; 260 263 struct rb_node **p, *parent; 261 - void *tofree[FQ_GC_MAX]; 262 - struct fq_flow *f; 263 - int i, fcnt = 0; 264 + int fcnt; 264 265 265 266 p = &root->rb_node; 266 267 parent = NULL; ··· 271 274 break; 272 275 273 276 if (fq_gc_candidate(f)) { 274 - tofree[fcnt++] = f; 275 - if (fcnt == FQ_GC_MAX) 276 - break; 277 + f->next = tofree; 278 + tofree = f; 277 279 } 278 280 279 281 if (f->sk > sk) ··· 281 285 p = &parent->rb_left; 282 286 } 283 287 284 - if (!fcnt) 288 + if (!tofree) 285 289 return; 286 290 287 - for (i = fcnt; i > 0; ) { 288 - f = tofree[--i]; 291 + fcnt = 0; 292 + while (tofree) { 293 + f = tofree; 294 + tofree = f->next; 289 295 rb_erase(&f->fq_node, root); 296 + kmem_cache_free(fq_flow_cachep, f); 297 + fcnt++; 290 298 } 291 299 q->flows -= fcnt; 292 300 q->inactive_flows -= fcnt; 293 301 q->stat_gc_flows += fcnt; 294 - 295 - kmem_cache_free_bulk(fq_flow_cachep, fcnt, tofree); 296 302 } 297 303 298 304 /* Fast path can be used if :