Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / net / core / skmsg.c
index b0fcd02..8162789 100644 (file)
@@ -462,7 +462,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
 
                        if (copied == len)
                                break;
-               } while (i != msg_rx->sg.end);
+               } while (!sg_is_last(sge));
 
                if (unlikely(peek)) {
                        msg_rx = sk_psock_next_msg(psock, msg_rx);
@@ -472,7 +472,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                }
 
                msg_rx->sg.start = i;
-               if (!sge->length && msg_rx->sg.start == msg_rx->sg.end) {
+               if (!sge->length && sg_is_last(sge)) {
                        msg_rx = sk_psock_dequeue_msg(psock);
                        kfree_sk_msg(msg_rx);
                }
@@ -497,23 +497,27 @@ bool sk_msg_is_readable(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(sk_msg_is_readable);
 
-static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
-                                                 struct sk_buff *skb)
+static struct sk_msg *alloc_sk_msg(void)
 {
        struct sk_msg *msg;
 
-       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+       msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_KERNEL);
+       if (unlikely(!msg))
                return NULL;
+       sg_init_marker(msg->sg.data, NR_MSG_FRAG_IDS);
+       return msg;
+}
 
-       if (!sk_rmem_schedule(sk, skb, skb->truesize))
+static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,
+                                                 struct sk_buff *skb)
+{
+       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
                return NULL;
 
-       msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_KERNEL);
-       if (unlikely(!msg))
+       if (!sk_rmem_schedule(sk, skb, skb->truesize))
                return NULL;
 
-       sk_msg_init(msg);
-       return msg;
+       return alloc_sk_msg();
 }
 
 static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
@@ -590,13 +594,12 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
 static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
                                     u32 off, u32 len)
 {
-       struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
+       struct sk_msg *msg = alloc_sk_msg();
        struct sock *sk = psock->sk;
        int err;
 
        if (unlikely(!msg))
                return -EAGAIN;
-       sk_msg_init(msg);
        skb_set_owner_r(skb, sk);
        err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg);
        if (err < 0)
@@ -720,6 +723,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
        psock->eval = __SK_NONE;
        psock->sk_proto = prot;
        psock->saved_unhash = prot->unhash;
+       psock->saved_destroy = prot->destroy;
        psock->saved_close = prot->close;
        psock->saved_write_space = sk->sk_write_space;
 
@@ -1164,21 +1168,14 @@ static void sk_psock_done_strp(struct sk_psock *psock)
 }
 #endif /* CONFIG_BPF_STREAM_PARSER */
 
-static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb,
-                                unsigned int offset, size_t orig_len)
+static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
 {
-       struct sock *sk = (struct sock *)desc->arg.data;
        struct sk_psock *psock;
        struct bpf_prog *prog;
        int ret = __SK_DROP;
-       int len = orig_len;
+       int len = skb->len;
 
-       /* clone here so sk_eat_skb() in tcp_read_sock does not drop our data */
-       skb = skb_clone(skb, GFP_ATOMIC);
-       if (!skb) {
-               desc->error = -ENOMEM;
-               return 0;
-       }
+       skb_get(skb);
 
        rcu_read_lock();
        psock = sk_psock(sk);
@@ -1191,12 +1188,10 @@ static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb,
        if (!prog)
                prog = READ_ONCE(psock->progs.skb_verdict);
        if (likely(prog)) {
-               skb->sk = sk;
                skb_dst_drop(skb);
                skb_bpf_redirect_clear(skb);
                ret = bpf_prog_run_pin_on_cpu(prog, skb);
                ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
-               skb->sk = NULL;
        }
        if (sk_psock_verdict_apply(psock, skb, ret) < 0)
                len = 0;
@@ -1208,16 +1203,10 @@ out:
 static void sk_psock_verdict_data_ready(struct sock *sk)
 {
        struct socket *sock = sk->sk_socket;
-       read_descriptor_t desc;
 
-       if (unlikely(!sock || !sock->ops || !sock->ops->read_sock))
+       if (unlikely(!sock || !sock->ops || !sock->ops->read_skb))
                return;
-
-       desc.arg.data = sk;
-       desc.error = 0;
-       desc.count = 1;
-
-       sock->ops->read_sock(sk, &desc, sk_psock_verdict_recv);
+       sock->ops->read_skb(sk, sk_psock_verdict_recv);
 }
 
 void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)