> diff --git a/net/core/skmsg.c b/net/core/skmsg.c
> index 2521b643fa05..347cb168f749 100644
> --- a/net/core/skmsg.c
> +++ b/net/core/skmsg.c
> @@ -586,21 +586,24 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
> }
>
> static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
> - u32 off, u32 len, bool take_ref);
> + u32 off, u32 len, bool take_ref,
> + bool settle_fwd_alloc);
> +static int sk_psock_skb_ingress_self_backlog(struct sk_psock *psock,
> + struct sk_buff *skb,
> + u32 off, u32 len, bool take_ref,
> + bool settle_fwd_alloc);
The forward declaration of sk_psock_skb_ingress_self() at line 588 is
now dead code. Before the commit, sk_psock_skb_ingress() (defined at
line 596) called it for the skb->sk == psock->sk case, which required
the forward declaration. This commit redirects that call site to
sk_psock_skb_ingress_self_backlog() instead. The only remaining caller
is sk_psock_verdict_apply(), which is well after the definition. Should
this prototype be removed?
[ ... ]
> @@ -618,34 +621,100 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
> return err;
> }
>
> -/* Puts an skb on the ingress queue of the socket already assigned to the
> - * skb. In this case we do not need to check memory limits or skb_set_owner_r
> - * because the skb is already accounted for here.
> +static int sk_psock_skb_ingress_self_assign(struct sock *sk,
> + struct sk_buff *skb,
> + bool settle_fwd_alloc)
> +{
> + /* Leave skbs already receive-accounted to sk untouched. */
> + if (skb->sk == sk && skb->destructor == sock_rfree)
> + return 0;
> +
> + if (settle_fwd_alloc) {
> + sock_owned_by_me(sk);
> +
> + if (!sk_rmem_schedule(sk, skb, 0))
> + return -EAGAIN;
> + }
> +
> + skb_set_owner_r(skb, sk);
> + return 0;
> +}
> +
> +/* Puts an skb on the ingress queue for psock->sk.
> + *
> + * If the skb already has receive ownership for this socket, leave socket
> + * memory accounting untouched. Otherwise, before assigning receive ownership
> + * to an unowned strparser SK_PASS skb, settle any existing sk_forward_alloc
> + * deficit from earlier clone charges.
> */
> static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
> - u32 off, u32 len, bool take_ref)
> + u32 off, u32 len, bool take_ref,
> + bool settle_fwd_alloc)
> {
> + struct sock *sk = psock->sk;
> struct sk_msg *msg = alloc_sk_msg(GFP_ATOMIC);
> + int err;
> +
> + if (unlikely(!msg))
> + return -EAGAIN;
> +
> + err = sk_psock_skb_ingress_self_assign(sk, skb, settle_fwd_alloc);
> + if (err)
> + goto free;
> +
> + /* This is used in tcp_bpf_recvmsg_parser() to determine whether the
> + * data originates from the socket's own protocol stack. No need to
> + * refcount sk because msg's lifetime is bound to sk via the ingress_msg.
> + */
> + msg->sk = sk;
> + err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg,
> + take_ref);
> + if (err < 0)
> + goto free;
> +
> + return err;
> +free:
> + kfree(msg);
> + return err;
> +}
> +
> +static int sk_psock_skb_ingress_self_backlog(struct sk_psock *psock,
> + struct sk_buff *skb,
> + u32 off, u32 len, bool take_ref,
> + bool settle_fwd_alloc)
> +{
> struct sock *sk = psock->sk;
> + struct sk_msg *msg = alloc_sk_msg(GFP_ATOMIC);
> int err;
>
> if (unlikely(!msg))
> return -EAGAIN;
> - skb_set_owner_r(skb, sk);
> +
> + lock_sock(sk);
> + err = sk_psock_skb_ingress_self_assign(sk, skb, settle_fwd_alloc);
> + release_sock(sk);
> + if (err)
> + goto free;
>
> /* This is used in tcp_bpf_recvmsg_parser() to determine whether the
> * data originates from the socket's own protocol stack. No need to
> * refcount sk because msg's lifetime is bound to sk via the ingress_msg.
> */
> msg->sk = sk;
> - err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, take_ref);
> + err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg,
> + take_ref);
> if (err < 0)
> - kfree(msg);
> + goto free;
> +
> + return err;
> +free:
> + kfree(msg);
> return err;
> }
Is GFP_ATOMIC necessary in sk_psock_skb_ingress_self_backlog()? The
function is only called from sk_psock_backlog(), which is the psock
backlog worker running in plain process context - the lock_sock() call
proves it can sleep. Before this commit, these same skbs were allocated
by sk_psock_create_ingress_msg() with alloc_sk_msg(GFP_KERNEL). Would
GFP_KERNEL be more appropriate here to avoid draining atomic reserves
and reduce the chance of allocation failure under memory pressure?
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32045036810
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.