kernel: use bulk free in kfree_skb_list to improve performance
[oweals/openwrt.git] / target / linux / generic / pending-4.14 / 650-net-use-bulk-free-in-kfree_skb_list.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 23 Mar 2019 18:26:10 +0100
3 Subject: [PATCH] net: use bulk free in kfree_skb_list
4
5 Since we're freeing multiple skbs, we might as well use bulk free to save a
6 few cycles. Use the same conditions for bulk free as in napi_consume_skb.
7
8 Signed-off-by: Felix Fietkau <nbd@nbd.name>
9 ---
10
11 --- a/net/core/skbuff.c
12 +++ b/net/core/skbuff.c
13 @@ -666,12 +666,44 @@ EXPORT_SYMBOL(kfree_skb);
14  
15  void kfree_skb_list(struct sk_buff *segs)
16  {
17 -       while (segs) {
18 -               struct sk_buff *next = segs->next;
19 +       struct sk_buff *next = segs;
20 +       void *skbs[16];
21 +       int n_skbs = 0;
22  
23 -               kfree_skb(segs);
24 -               segs = next;
25 +       while ((segs = next) != NULL) {
26 +               next = segs->next;
27 +
28 +               if (segs->fclone != SKB_FCLONE_UNAVAILABLE) {
29 +                       kfree_skb(segs);
30 +                       continue;
31 +               }
32 +
33 +               if (!skb_unref(segs))
34 +                       continue;
35 +
36 +               trace_kfree_skb(segs, __builtin_return_address(0));
37 +
38 +               /* drop skb->head and call any destructors for packet */
39 +               skb_release_all(segs);
40 +
41 +#ifdef CONFIG_SLUB
42 +               /* SLUB writes into objects when freeing */
43 +               prefetchw(segs);
44 +#endif
45 +
46 +               skbs[n_skbs++] = segs;
47 +
48 +               if (n_skbs < ARRAY_SIZE(skbs))
49 +                       continue;
50 +
51 +               kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
52 +               n_skbs = 0;
53         }
54 +
55 +       if (!n_skbs)
56 +               return;
57 +
58 +       kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
59  }
60  EXPORT_SYMBOL(kfree_skb_list);
61