udp: Convert udp_sendpage() to use MSG_SPLICE_PAGES
authorDavid Howells <dhowells@redhat.com>
Mon, 22 May 2023 12:11:22 +0000 (13:11 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 24 May 2023 03:48:27 +0000 (20:48 -0700)
Convert udp_sendpage() to use sendmsg() with MSG_SPLICE_PAGES rather than
directly splicing in the pages itself.

This allows ->sendpage() to be replaced by something that can handle
multiple multipage folios in a single transaction.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
cc: David Ahern <dsahern@kernel.org>
cc: Jens Axboe <axboe@kernel.dk>
cc: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/udp.c

index aa32afd..2879dc6 100644 (file)
@@ -1332,54 +1332,15 @@ EXPORT_SYMBOL(udp_sendmsg);
 int udp_sendpage(struct sock *sk, struct page *page, int offset,
                 size_t size, int flags)
 {
-       struct inet_sock *inet = inet_sk(sk);
-       struct udp_sock *up = udp_sk(sk);
-       int ret;
+       struct bio_vec bvec;
+       struct msghdr msg = { .msg_flags = flags | MSG_SPLICE_PAGES };
 
        if (flags & MSG_SENDPAGE_NOTLAST)
-               flags |= MSG_MORE;
-
-       if (!up->pending) {
-               struct msghdr msg = {   .msg_flags = flags|MSG_MORE };
-
-               /* Call udp_sendmsg to specify destination address which
-                * sendpage interface can't pass.
-                * This will succeed only when the socket is connected.
-                */
-               ret = udp_sendmsg(sk, &msg, 0);
-               if (ret < 0)
-                       return ret;
-       }
-
-       lock_sock(sk);
+               msg.msg_flags |= MSG_MORE;
 
-       if (unlikely(!up->pending)) {
-               release_sock(sk);
-
-               net_dbg_ratelimited("cork failed\n");
-               return -EINVAL;
-       }
-
-       ret = ip_append_page(sk, &inet->cork.fl.u.ip4,
-                            page, offset, size, flags);
-       if (ret == -EOPNOTSUPP) {
-               release_sock(sk);
-               return sock_no_sendpage(sk->sk_socket, page, offset,
-                                       size, flags);
-       }
-       if (ret < 0) {
-               udp_flush_pending_frames(sk);
-               goto out;
-       }
-
-       up->len += size;
-       if (!(READ_ONCE(up->corkflag) || (flags&MSG_MORE)))
-               ret = udp_push_pending_frames(sk);
-       if (!ret)
-               ret = size;
-out:
-       release_sock(sk);
-       return ret;
+       bvec_set_page(&bvec, page, size, offset);
+       iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
+       return udp_sendmsg(sk, &msg, size);
 }
 
 #define UDP_SKB_IS_STATELESS 0x80000000