* [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
@ 2026-08-16 23:56 Kyle Zeng
2026-08-18 14:06 ` Willem de Bruijn
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Kyle Zeng @ 2026-08-16 23:56 UTC (permalink / raw)
To: netdev
Cc: Eric Dumazet, Jakub Kicinski, David S . Miller, Willem de Bruijn,
Muhammad_Hazley_SAMSUDIN_from.TP, Kyle Zeng, stable
AF_PACKET TX_RING skbs keep a raw pointer to their ring frame. The skb
page references preserve page-backed ring blocks after pg_vec is freed,
but they do not preserve a vmalloc mapping.
tpacket_destruct_skb() currently drops the pending reference before
writing the timestamp and TP_STATUS_AVAILABLE to the frame. Move the
decrement after those stores. The smp_wmb() in __packet_set_status()
orders the frame stores before the decrement.
Also recheck pending TX frames under pg_vec_lock before non-closing
ring replacement, so a racing send cannot add a pending skb between
the initial check and the ring swap.
Ring allocation can produce a mixture of page-backed and vmalloc-backed
blocks. Allocate deferred-work storage during TX ring setup when the
first vmalloc-backed block is encountered, and keep its pointer in the
pg_vec allocation header. If allocation fails, return -ENOMEM from ring
setup. On socket close, a non-NULL pointer identifies a vmalloc-backed
vector without a scan. If TX skbs remain, defer the whole vector to
system_long_wq.
After pg_vec is detached, a late destructor can skip the pending
decrement. Use socket write-memory accounting as the deferred lifetime
gate instead: an skb remains charged through its final sock_wfree(),
after all ring-frame accesses. The delayed work retains a socket
reference and reschedules itself until no TX skbs remain.
Move pending_refcnt release to packet_sock_destruct() so late skb
destructors and deferred cleanup can safely use it after
packet_release(). Page-backed teardown remains synchronous, and no lock
is added to the TX completion hot path.
Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
Suggested-by: Eric Dumazet <edumazet@google.com>
Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Assisted-by: Codex:gpt-5.6-sol
---
Changes in v2:
- Allocate cleanup work during setup, only for vmalloc-backed TX rings.
- Keep its pointer in the pg_vec allocation header; remove the teardown
detection scan, allocation, and synchronous fallback.
- Use socket write-memory accounting for both the close-time decision
and the deferred worker.
- Recheck pending TX frames under pg_vec_lock before non-closing swaps.
- Rebase onto f5bbbfec59b4.
net/packet/af_packet.c | 96 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 87 insertions(+), 9 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 435756877aba..7bb5d8ca1593 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -88,6 +88,7 @@
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
#include <linux/percpu.h>
+#include <linux/workqueue.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
#endif
@@ -1341,6 +1342,8 @@ static void packet_sock_destruct(struct sock *sk)
WARN_ON(atomic_read(&sk->sk_rmem_alloc));
WARN_ON(refcount_read(&sk->sk_wmem_alloc));
+ packet_free_pending(pkt_sk(sk));
+
if (!sock_flag(sk, SOCK_DEAD)) {
pr_err("Attempt to release alive packet socket: %p\n", sk);
return;
@@ -2534,11 +2537,11 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
__u32 ts;
ph = skb_zcopy_get_nouarg(skb);
- packet_dec_pending(&po->tx_ring);
ts = __packet_set_timestamp(po, ph, skb);
__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
+ packet_dec_pending(&po->tx_ring);
complete(&po->skb_completion);
}
@@ -3204,7 +3207,6 @@ static int packet_release(struct socket *sock)
/* Purge queues */
skb_queue_purge(&sk->sk_receive_queue);
- packet_free_pending(po);
sock_put(sk);
return 0;
@@ -4367,11 +4369,26 @@ static const struct vm_operations_struct packet_mmap_ops = {
.close = packet_mm_close,
};
+struct packet_pg_vec {
+ struct packet_pg_vec_free *deferred;
+ unsigned int order;
+ unsigned int len;
+ struct pgv pg_vec[] __counted_by(len);
+};
+
+struct packet_pg_vec_free {
+ struct delayed_work work;
+ struct sock *sk;
+ struct packet_pg_vec *vec;
+};
+
static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
unsigned int len)
{
+ struct packet_pg_vec *vec;
int i;
+ vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
for (i = 0; i < len; i++) {
if (likely(pg_vec[i].buffer)) {
if (is_vmalloc_addr(pg_vec[i].buffer))
@@ -4382,7 +4399,46 @@ static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
pg_vec[i].buffer = NULL;
}
}
- kfree(pg_vec);
+ kfree(vec->deferred);
+ kfree(vec);
+}
+
+static void packet_free_pg_vec_work(struct work_struct *work)
+{
+ struct packet_pg_vec_free *deferred;
+ struct packet_pg_vec *vec;
+ struct sock *sk;
+
+ deferred = container_of_const(to_delayed_work(work),
+ struct packet_pg_vec_free, work);
+ vec = deferred->vec;
+ sk = deferred->sk;
+ if (sk_wmem_alloc_get(sk)) {
+ queue_delayed_work(system_long_wq, &deferred->work, 1);
+ return;
+ }
+
+ free_pg_vec(vec->pg_vec, vec->order, vec->len);
+ sock_put(sk);
+}
+
+static void packet_free_tx_ring(struct sock *sk, struct pgv *pg_vec,
+ unsigned int order, unsigned int len)
+{
+ struct packet_pg_vec_free *deferred;
+ struct packet_pg_vec *vec;
+
+ vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
+ deferred = vec->deferred;
+ if (!deferred || !sk_wmem_alloc_get(sk)) {
+ free_pg_vec(pg_vec, order, len);
+ return;
+ }
+
+ /* A detached ring's pending count can miss late skb destructors. */
+ deferred->sk = sk;
+ sock_hold(sk);
+ queue_delayed_work(system_long_wq, &deferred->work, 0);
}
static char *alloc_one_pg_vec_page(unsigned long order)
@@ -4410,20 +4466,35 @@ static char *alloc_one_pg_vec_page(unsigned long order)
return NULL;
}
-static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
+static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order, bool tx_ring)
{
unsigned int block_nr = req->tp_block_nr;
+ struct packet_pg_vec *vec;
struct pgv *pg_vec;
int i;
- pg_vec = kzalloc_objs(struct pgv, block_nr, GFP_KERNEL | __GFP_NOWARN);
- if (unlikely(!pg_vec))
- goto out;
+ vec = kzalloc_flex(*vec, pg_vec, block_nr, GFP_KERNEL | __GFP_NOWARN);
+ if (unlikely(!vec))
+ return NULL;
+ vec->order = order;
+ vec->len = block_nr;
+ pg_vec = vec->pg_vec;
for (i = 0; i < block_nr; i++) {
pg_vec[i].buffer = alloc_one_pg_vec_page(order);
if (unlikely(!pg_vec[i].buffer))
goto out_free_pgvec;
+
+ if (tx_ring && !vec->deferred &&
+ is_vmalloc_addr(pg_vec[i].buffer)) {
+ vec->deferred = kzalloc_obj(*vec->deferred,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!vec->deferred)
+ goto out_free_pgvec;
+ vec->deferred->vec = vec;
+ INIT_DELAYED_WORK(&vec->deferred->work,
+ packet_free_pg_vec_work);
+ }
}
out:
@@ -4506,7 +4577,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
err = -ENOMEM;
order = get_order(req->tp_block_size);
- pg_vec = alloc_pg_vec(req, order);
+ pg_vec = alloc_pg_vec(req, order, tx_ring);
if (unlikely(!pg_vec))
goto out;
switch (po->tp_version) {
@@ -4558,6 +4629,9 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
err = -EBUSY;
mutex_lock(&po->pg_vec_lock);
if (closing || atomic_long_read(&po->mapped) == 0) {
+ if (tx_ring && !closing && packet_read_pending(rb))
+ goto out_unlock;
+
err = 0;
spin_lock_bh(&rb_queue->lock);
swap(rb->pg_vec, pg_vec);
@@ -4579,6 +4653,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
pr_err("packet_mmap: vma is busy: %ld\n",
atomic_long_read(&po->mapped));
}
+out_unlock:
mutex_unlock(&po->pg_vec_lock);
spin_lock(&po->bind_lock);
@@ -4600,7 +4675,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
out_free_pg_vec:
if (pg_vec) {
bitmap_free(rx_owner_map);
- free_pg_vec(pg_vec, order, req->tp_block_nr);
+ if (tx_ring && closing)
+ packet_free_tx_ring(sk, pg_vec, order, req->tp_block_nr);
+ else
+ free_pg_vec(pg_vec, order, req->tp_block_nr);
}
out:
return err;
base-commit: f5bbbfec59b4e2fb7520a91de3df8a6174325d6a
--
2.55.0.openai.347.g2b0ba75e4a61
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
2026-08-16 23:56 [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish Kyle Zeng
@ 2026-08-18 14:06 ` Willem de Bruijn
2026-08-20 2:10 ` Willem de Bruijn
2026-08-20 19:42 ` Jakub Kicinski
2026-08-20 20:30 ` patchwork-bot+netdevbpf
2 siblings, 1 reply; 6+ messages in thread
From: Willem de Bruijn @ 2026-08-18 14:06 UTC (permalink / raw)
To: Kyle Zeng, netdev
Cc: Eric Dumazet, Jakub Kicinski, David S . Miller, Willem de Bruijn,
Muhammad_Hazley_SAMSUDIN_from.TP, Kyle Zeng, stable
Kyle Zeng wrote:
> AF_PACKET TX_RING skbs keep a raw pointer to their ring frame. The skb
> page references preserve page-backed ring blocks after pg_vec is freed,
> but they do not preserve a vmalloc mapping.
Claude shows an interesting case where this page-backed statement does
not hold: if the entire skb is linear. Not for this patch, but a
similar case.
> tpacket_destruct_skb() currently drops the pending reference before
> writing the timestamp and TP_STATUS_AVAILABLE to the frame. Move the
> decrement after those stores. The smp_wmb() in __packet_set_status()
> orders the frame stores before the decrement.
>
> Also recheck pending TX frames under pg_vec_lock before non-closing
> ring replacement, so a racing send cannot add a pending skb between
> the initial check and the ring swap.
>
> Ring allocation can produce a mixture of page-backed and vmalloc-backed
> blocks. Allocate deferred-work storage during TX ring setup when the
> first vmalloc-backed block is encountered, and keep its pointer in the
> pg_vec allocation header. If allocation fails, return -ENOMEM from ring
> setup. On socket close, a non-NULL pointer identifies a vmalloc-backed
> vector without a scan. If TX skbs remain, defer the whole vector to
> system_long_wq.
>
> After pg_vec is detached, a late destructor can skip the pending
> decrement. Use socket write-memory accounting as the deferred lifetime
> gate instead: an skb remains charged through its final sock_wfree(),
> after all ring-frame accesses. The delayed work retains a socket
> reference and reschedules itself until no TX skbs remain.
>
> Move pending_refcnt release to packet_sock_destruct() so late skb
> destructors and deferred cleanup can safely use it after
> packet_release(). Page-backed teardown remains synchronous, and no lock
> is added to the TX completion hot path.
This one patch combines multiple fixes. If and only if a respin is
needed, it may be good to break it up to help understanding.
> Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
> Cc: stable@vger.kernel.org
> Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
> Suggested-by: Eric Dumazet <edumazet@google.com>
> Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> Assisted-by: Codex:gpt-5.6-sol
> +struct packet_pg_vec {
> + struct packet_pg_vec_free *deferred;
> + unsigned int order;
> + unsigned int len;
> + struct pgv pg_vec[] __counted_by(len);
> +};
> +
> +struct packet_pg_vec_free {
> + struct delayed_work work;
> + struct sock *sk;
> + struct packet_pg_vec *vec;
> +};
> @@ -4382,7 +4399,46 @@ static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
> +static void packet_free_pg_vec_work(struct work_struct *work)
> +{
> + struct packet_pg_vec_free *deferred;
> + struct packet_pg_vec *vec;
> + struct sock *sk;
> +
> + deferred = container_of_const(to_delayed_work(work),
> + struct packet_pg_vec_free, work);
> + vec = deferred->vec;
> + sk = deferred->sk;
> + if (sk_wmem_alloc_get(sk)) {
> + queue_delayed_work(system_long_wq, &deferred->work, 1);
Can this keep requeueing itself? Claude suggests using pending ring
count as gate.
> +static void packet_free_tx_ring(struct sock *sk, struct pgv *pg_vec,
> + unsigned int order, unsigned int len)
> +{
> + struct packet_pg_vec_free *deferred;
> + struct packet_pg_vec *vec;
> +
> + vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
> + deferred = vec->deferred;
> + if (!deferred || !sk_wmem_alloc_get(sk)) {
> + free_pg_vec(pg_vec, order, len);
> + return;
> + }
> +
> + /* A detached ring's pending count can miss late skb destructors. */
> + deferred->sk = sk;
> + sock_hold(sk);
> + queue_delayed_work(system_long_wq, &deferred->work, 0);
> }
>
> static char *alloc_one_pg_vec_page(unsigned long order)
> @@ -4410,20 +4466,35 @@ static char *alloc_one_pg_vec_page(unsigned long order)
> return NULL;
> }
>
> -static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
> +static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order, bool tx_ring)
> {
> unsigned int block_nr = req->tp_block_nr;
> + struct packet_pg_vec *vec;
> struct pgv *pg_vec;
> int i;
>
> - pg_vec = kzalloc_objs(struct pgv, block_nr, GFP_KERNEL | __GFP_NOWARN);
> - if (unlikely(!pg_vec))
> - goto out;
> + vec = kzalloc_flex(*vec, pg_vec, block_nr, GFP_KERNEL | __GFP_NOWARN);
> + if (unlikely(!vec))
> + return NULL;
> + vec->order = order;
> + vec->len = block_nr;
> + pg_vec = vec->pg_vec;
>
> for (i = 0; i < block_nr; i++) {
> pg_vec[i].buffer = alloc_one_pg_vec_page(order);
> if (unlikely(!pg_vec[i].buffer))
> goto out_free_pgvec;
> +
> + if (tx_ring && !vec->deferred &&
> + is_vmalloc_addr(pg_vec[i].buffer)) {
> + vec->deferred = kzalloc_obj(*vec->deferred,
> + GFP_KERNEL | __GFP_NOWARN);
> + if (!vec->deferred)
> + goto out_free_pgvec;
> + vec->deferred->vec = vec;
The nested structures are fairly complex.
Would it make sense to avoid the separate packet_pg_vec_free, fold
that into packet_pg_vec and use a different field to identify
whether vmalloc backed pages are used. Maybe sk, or even a new
boolean field has_vmalloc, for readability
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
2026-08-18 14:06 ` Willem de Bruijn
@ 2026-08-20 2:10 ` Willem de Bruijn
0 siblings, 0 replies; 6+ messages in thread
From: Willem de Bruijn @ 2026-08-20 2:10 UTC (permalink / raw)
To: Willem de Bruijn, Kyle Zeng, netdev
Cc: Eric Dumazet, Jakub Kicinski, David S . Miller, Willem de Bruijn,
Muhammad_Hazley_SAMSUDIN_from.TP, Kyle Zeng, stable
Willem de Bruijn wrote:
> Kyle Zeng wrote:
> > AF_PACKET TX_RING skbs keep a raw pointer to their ring frame. The skb
> > page references preserve page-backed ring blocks after pg_vec is freed,
> > but they do not preserve a vmalloc mapping.
>
> Claude shows an interesting case where this page-backed statement does
> not hold: if the entire skb is linear. Not for this patch, but a
> similar case.
>
> > tpacket_destruct_skb() currently drops the pending reference before
> > writing the timestamp and TP_STATUS_AVAILABLE to the frame. Move the
> > decrement after those stores. The smp_wmb() in __packet_set_status()
> > orders the frame stores before the decrement.
> >
> > Also recheck pending TX frames under pg_vec_lock before non-closing
> > ring replacement, so a racing send cannot add a pending skb between
> > the initial check and the ring swap.
> >
> > Ring allocation can produce a mixture of page-backed and vmalloc-backed
> > blocks. Allocate deferred-work storage during TX ring setup when the
> > first vmalloc-backed block is encountered, and keep its pointer in the
> > pg_vec allocation header. If allocation fails, return -ENOMEM from ring
> > setup. On socket close, a non-NULL pointer identifies a vmalloc-backed
> > vector without a scan. If TX skbs remain, defer the whole vector to
> > system_long_wq.
> >
> > After pg_vec is detached, a late destructor can skip the pending
> > decrement. Use socket write-memory accounting as the deferred lifetime
> > gate instead: an skb remains charged through its final sock_wfree(),
> > after all ring-frame accesses. The delayed work retains a socket
> > reference and reschedules itself until no TX skbs remain.
> >
> > Move pending_refcnt release to packet_sock_destruct() so late skb
> > destructors and deferred cleanup can safely use it after
> > packet_release(). Page-backed teardown remains synchronous, and no lock
> > is added to the TX completion hot path.
>
> This one patch combines multiple fixes. If and only if a respin is
> needed, it may be good to break it up to help understanding.
>
> > Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
> > Cc: stable@vger.kernel.org
> > Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
> > Suggested-by: Eric Dumazet <edumazet@google.com>
> > Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> > Assisted-by: Codex:gpt-5.6-sol
>
> > +struct packet_pg_vec {
> > + struct packet_pg_vec_free *deferred;
> > + unsigned int order;
> > + unsigned int len;
> > + struct pgv pg_vec[] __counted_by(len);
> > +};
> > +
> > +struct packet_pg_vec_free {
> > + struct delayed_work work;
> > + struct sock *sk;
> > + struct packet_pg_vec *vec;
> > +};
>
> > @@ -4382,7 +4399,46 @@ static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
> > +static void packet_free_pg_vec_work(struct work_struct *work)
> > +{
> > + struct packet_pg_vec_free *deferred;
> > + struct packet_pg_vec *vec;
> > + struct sock *sk;
> > +
> > + deferred = container_of_const(to_delayed_work(work),
> > + struct packet_pg_vec_free, work);
> > + vec = deferred->vec;
> > + sk = deferred->sk;
> > + if (sk_wmem_alloc_get(sk)) {
> > + queue_delayed_work(system_long_wq, &deferred->work, 1);
>
> Can this keep requeueing itself? Claude suggests using pending ring
> count as gate.
>
> > +static void packet_free_tx_ring(struct sock *sk, struct pgv *pg_vec,
> > + unsigned int order, unsigned int len)
> > +{
> > + struct packet_pg_vec_free *deferred;
> > + struct packet_pg_vec *vec;
> > +
> > + vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
> > + deferred = vec->deferred;
> > + if (!deferred || !sk_wmem_alloc_get(sk)) {
> > + free_pg_vec(pg_vec, order, len);
> > + return;
> > + }
> > +
> > + /* A detached ring's pending count can miss late skb destructors. */
> > + deferred->sk = sk;
> > + sock_hold(sk);
> > + queue_delayed_work(system_long_wq, &deferred->work, 0);
> > }
> >
> > static char *alloc_one_pg_vec_page(unsigned long order)
> > @@ -4410,20 +4466,35 @@ static char *alloc_one_pg_vec_page(unsigned long order)
> > return NULL;
> > }
> >
> > -static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
> > +static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order, bool tx_ring)
> > {
> > unsigned int block_nr = req->tp_block_nr;
> > + struct packet_pg_vec *vec;
> > struct pgv *pg_vec;
> > int i;
> >
> > - pg_vec = kzalloc_objs(struct pgv, block_nr, GFP_KERNEL | __GFP_NOWARN);
> > - if (unlikely(!pg_vec))
> > - goto out;
> > + vec = kzalloc_flex(*vec, pg_vec, block_nr, GFP_KERNEL | __GFP_NOWARN);
> > + if (unlikely(!vec))
> > + return NULL;
> > + vec->order = order;
> > + vec->len = block_nr;
> > + pg_vec = vec->pg_vec;
> >
> > for (i = 0; i < block_nr; i++) {
> > pg_vec[i].buffer = alloc_one_pg_vec_page(order);
> > if (unlikely(!pg_vec[i].buffer))
> > goto out_free_pgvec;
> > +
> > + if (tx_ring && !vec->deferred &&
> > + is_vmalloc_addr(pg_vec[i].buffer)) {
> > + vec->deferred = kzalloc_obj(*vec->deferred,
> > + GFP_KERNEL | __GFP_NOWARN);
> > + if (!vec->deferred)
> > + goto out_free_pgvec;
> > + vec->deferred->vec = vec;
>
> The nested structures are fairly complex.
>
> Would it make sense to avoid the separate packet_pg_vec_free, fold
> that into packet_pg_vec and use a different field to identify
> whether vmalloc backed pages are used. Maybe sk, or even a new
> boolean field has_vmalloc, for readability
To be clear, these are questions, not blocking issues.
Reviewed-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
2026-08-16 23:56 [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish Kyle Zeng
2026-08-18 14:06 ` Willem de Bruijn
@ 2026-08-20 19:42 ` Jakub Kicinski
2026-08-20 19:45 ` Kyle Zeng
2026-08-20 20:30 ` patchwork-bot+netdevbpf
2 siblings, 1 reply; 6+ messages in thread
From: Jakub Kicinski @ 2026-08-20 19:42 UTC (permalink / raw)
To: Kyle Zeng
Cc: netdev, Eric Dumazet, David S . Miller, Willem de Bruijn,
Muhammad_Hazley_SAMSUDIN_from.TP, stable
On Sun, 16 Aug 2026 16:56:46 -0700 Kyle Zeng wrote:
> Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
> Cc: stable@vger.kernel.org
> Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
> Suggested-by: Eric Dumazet <edumazet@google.com>
> Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> Assisted-by: Codex:gpt-5.6-sol
Kyle, we're missing your sign-off tag here.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
2026-08-20 19:42 ` Jakub Kicinski
@ 2026-08-20 19:45 ` Kyle Zeng
0 siblings, 0 replies; 6+ messages in thread
From: Kyle Zeng @ 2026-08-20 19:45 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, Eric Dumazet, David S . Miller, Willem de Bruijn,
Muhammad_Hazley_SAMSUDIN_from.TP, stable
On Thu, Aug 20, 2026 at 12:42:53PM -0700, Jakub Kicinski wrote:
> On Sun, 16 Aug 2026 16:56:46 -0700 Kyle Zeng wrote:
> > Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
> > Cc: stable@vger.kernel.org
> > Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
> > Suggested-by: Eric Dumazet <edumazet@google.com>
> > Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> > Assisted-by: Codex:gpt-5.6-sol
>
> Kyle, we're missing your sign-off tag here.
Apologies, here is the tag:
Signed-off-by: Kyle Zeng <kylebot@openai.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish
2026-08-16 23:56 [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish Kyle Zeng
2026-08-18 14:06 ` Willem de Bruijn
2026-08-20 19:42 ` Jakub Kicinski
@ 2026-08-20 20:30 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-20 20:30 UTC (permalink / raw)
To: Kyle Zeng
Cc: netdev, edumazet, kuba, davem, willemdebruijn.kernel,
Muhammad_Hazley_SAMSUDIN_from.TP, stable
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sun, 16 Aug 2026 16:56:46 -0700 you wrote:
> AF_PACKET TX_RING skbs keep a raw pointer to their ring frame. The skb
> page references preserve page-backed ring blocks after pg_vec is freed,
> but they do not preserve a vmalloc mapping.
>
> tpacket_destruct_skb() currently drops the pending reference before
> writing the timestamp and TP_STATUS_AVAILABLE to the frame. Move the
> decrement after those stores. The smp_wmb() in __packet_set_status()
> orders the frame stores before the decrement.
>
> [...]
Here is the summary with links:
- [net,v2] net/packet: defer vmalloc TX_RING free until skbs finish
https://git.kernel.org/netdev/net/c/992cc9f94ca9
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-20 20:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-16 23:56 [PATCH net v2] net/packet: defer vmalloc TX_RING free until skbs finish Kyle Zeng
2026-08-18 14:06 ` Willem de Bruijn
2026-08-20 2:10 ` Willem de Bruijn
2026-08-20 19:42 ` Jakub Kicinski
2026-08-20 19:45 ` Kyle Zeng
2026-08-20 20:30 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox