]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net_sched: add tcf_kfree_skb_list() helper
authorEric Dumazet <edumazet@google.com>
Fri, 21 Nov 2025 08:32:54 +0000 (08:32 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 25 Nov 2025 15:10:32 +0000 (16:10 +0100)
Using kfree_skb_list_reason() to free list of skbs from qdisc
operations seems wrong as each skb might have a different drop reason.

Cleanup __dev_xmit_skb() to call tcf_kfree_skb_list() once
in preparation of the following patch.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20251121083256.674562-13-edumazet@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
include/net/sch_generic.h
net/core/dev.c

index 79501499dafba56271b9ebd97a8f379ffdc83cac..b8092d0378a0cafa290123d17c1b0ba787cd0680 100644 (file)
@@ -1105,6 +1105,17 @@ static inline void tcf_set_drop_reason(const struct sk_buff *skb,
        tc_skb_cb(skb)->drop_reason = reason;
 }
 
+static inline void tcf_kfree_skb_list(struct sk_buff *skb)
+{
+       while (unlikely(skb)) {
+               struct sk_buff *next = skb->next;
+
+               prefetch(next);
+               kfree_skb_reason(skb, tcf_get_drop_reason(skb));
+               skb = next;
+       }
+}
+
 /* Instead of calling kfree_skb() while root qdisc lock is held,
  * queue the skb for future freeing at end of __dev_xmit_skb()
  */
index 10042139dbb054b9a93dfb019477a80263feb029..e865cdb9b6966225072dc44a86610b9c7828bd8c 100644 (file)
@@ -4162,7 +4162,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
                                __qdisc_run(q);
                                qdisc_run_end(q);
 
-                               goto no_lock_out;
+                               goto free_skbs;
                        }
 
                        qdisc_bstats_cpu_update(q, skb);
@@ -4176,12 +4176,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 
                rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
                qdisc_run(q);
-
-no_lock_out:
-               if (unlikely(to_free))
-                       kfree_skb_list_reason(to_free,
-                                             tcf_get_drop_reason(to_free));
-               return rc;
+               goto free_skbs;
        }
 
        /* Open code llist_add(&skb->ll_node, &q->defer_list) + queue limit.
@@ -4257,9 +4252,9 @@ no_lock_out:
        }
 unlock:
        spin_unlock(root_lock);
-       if (unlikely(to_free))
-               kfree_skb_list_reason(to_free,
-                                     tcf_get_drop_reason(to_free));
+
+free_skbs:
+       tcf_kfree_skb_list(to_free);
        return rc;
 }