chelsio: Convert chtls_sendpage() to use MSG_SPLICE_PAGES
authorDavid Howells <dhowells@redhat.com>
Wed, 31 May 2023 11:00:08 +0000 (12:00 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 1 Jun 2023 11:41:36 +0000 (13:41 +0200)
Convert chtls_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: Ayush Sawal <ayush.sawal@chelsio.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Jens Axboe <axboe@kernel.dk>
cc: Matthew Wilcox <willy@infradead.org>
cc: netdev@vger.kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c

index 1d08386..5724bbb 100644 (file)
@@ -1240,110 +1240,15 @@ out_err:
 int chtls_sendpage(struct sock *sk, struct page *page,
                   int offset, size_t size, int flags)
 {
-       struct chtls_sock *csk;
-       struct chtls_dev *cdev;
-       int mss, err, copied;
-       struct tcp_sock *tp;
-       long timeo;
-
-       tp = tcp_sk(sk);
-       copied = 0;
-       csk = rcu_dereference_sk_user_data(sk);
-       cdev = csk->cdev;
-       lock_sock(sk);
-       timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+       struct msghdr msg = { .msg_flags = flags | MSG_SPLICE_PAGES, };
+       struct bio_vec bvec;
 
-       err = sk_stream_wait_connect(sk, &timeo);
-       if (!sk_in_state(sk, TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
-           err != 0)
-               goto out_err;
-
-       mss = csk->mss;
-       csk_set_flag(csk, CSK_TX_MORE_DATA);
-
-       while (size > 0) {
-               struct sk_buff *skb = skb_peek_tail(&csk->txq);
-               int copy, i;
-
-               if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) ||
-                   (copy = mss - skb->len) <= 0) {
-new_buf:
-                       if (!csk_mem_free(cdev, sk))
-                               goto wait_for_sndbuf;
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               msg.msg_flags |= MSG_MORE;
 
-                       if (is_tls_tx(csk)) {
-                               skb = get_record_skb(sk,
-                                                    select_size(sk, size,
-                                                                flags,
-                                                                TX_TLSHDR_LEN),
-                                                    true);
-                       } else {
-                               skb = get_tx_skb(sk, 0);
-                       }
-                       if (!skb)
-                               goto wait_for_memory;
-                       copy = mss;
-               }
-               if (copy > size)
-                       copy = size;
-
-               i = skb_shinfo(skb)->nr_frags;
-               if (skb_can_coalesce(skb, i, page, offset)) {
-                       skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
-               } else if (i < MAX_SKB_FRAGS) {
-                       get_page(page);
-                       skb_fill_page_desc(skb, i, page, offset, copy);
-               } else {
-                       tx_skb_finalize(skb);
-                       push_frames_if_head(sk);
-                       goto new_buf;
-               }
-
-               skb->len += copy;
-               if (skb->len == mss)
-                       tx_skb_finalize(skb);
-               skb->data_len += copy;
-               skb->truesize += copy;
-               sk->sk_wmem_queued += copy;
-               tp->write_seq += copy;
-               copied += copy;
-               offset += copy;
-               size -= copy;
-
-               if (corked(tp, flags) &&
-                   (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)))
-                       ULP_SKB_CB(skb)->flags |= ULPCB_FLAG_NO_APPEND;
-
-               if (!size)
-                       break;
-
-               if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND))
-                       push_frames_if_head(sk);
-               continue;
-wait_for_sndbuf:
-               set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-wait_for_memory:
-               err = csk_wait_memory(cdev, sk, &timeo);
-               if (err)
-                       goto do_error;
-       }
-out:
-       csk_reset_flag(csk, CSK_TX_MORE_DATA);
-       if (copied)
-               chtls_tcp_push(sk, flags);
-done:
-       release_sock(sk);
-       return copied;
-
-do_error:
-       if (copied)
-               goto out;
-
-out_err:
-       if (csk_conn_inline(csk))
-               csk_reset_flag(csk, CSK_TX_MORE_DATA);
-       copied = sk_stream_error(sk, flags, err);
-       goto done;
+       bvec_set_page(&bvec, page, size, offset);
+       iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
+       return chtls_sendmsg(sk, &msg, size);
 }
 
 static void chtls_select_window(struct sock *sk)