io_uring/net: add non-bvec sg chunking callback
authorPavel Begunkov <asml.silence@gmail.com>
Thu, 8 Sep 2022 12:20:32 +0000 (13:20 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 21 Sep 2022 16:30:43 +0000 (10:30 -0600)
Add a sg_from_iter() for when we initiate non-bvec zerocopy sends, which
helps us to remove some extra steps from io_sg_from_iter(). The only
thing the new function has to do before giving control away to
__zerocopy_sg_from_iter() is to check if the skb has managed frags and
downgrade them if so.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/cda3dea0d36f7931f63a70f350130f085ac3f3dd.1662639236.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/net.c

index 07f6b9e..9b76ceb 100644 (file)
@@ -948,6 +948,13 @@ int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        return 0;
 }
 
+static int io_sg_from_iter_iovec(struct sock *sk, struct sk_buff *skb,
+                                struct iov_iter *from, size_t length)
+{
+       skb_zcopy_downgrade_managed(skb);
+       return __zerocopy_sg_from_iter(NULL, sk, skb, from, length);
+}
+
 static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
                           struct iov_iter *from, size_t length)
 {
@@ -958,13 +965,10 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
        ssize_t copied = 0;
        unsigned long truesize = 0;
 
-       if (!shinfo->nr_frags)
+       if (!frag)
                shinfo->flags |= SKBFL_MANAGED_FRAG_REFS;
-
-       if (!skb_zcopy_managed(skb) || !iov_iter_is_bvec(from)) {
-               skb_zcopy_downgrade_managed(skb);
+       else if (unlikely(!skb_zcopy_managed(skb)))
                return __zerocopy_sg_from_iter(NULL, sk, skb, from, length);
-       }
 
        bi.bi_size = min(from->count, length);
        bi.bi_bvec_done = from->iov_offset;
@@ -1045,6 +1049,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                                        (u64)(uintptr_t)zc->buf, zc->len);
                if (unlikely(ret))
                        return ret;
+               msg.sg_from_iter = io_sg_from_iter;
        } else {
                ret = import_single_range(WRITE, zc->buf, zc->len, &iov,
                                          &msg.msg_iter);
@@ -1053,6 +1058,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                ret = io_notif_account_mem(zc->notif, zc->len);
                if (unlikely(ret))
                        return ret;
+               msg.sg_from_iter = io_sg_from_iter_iovec;
        }
 
        msg_flags = zc->msg_flags | MSG_ZEROCOPY;
@@ -1063,7 +1069,6 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 
        msg.msg_flags = msg_flags;
        msg.msg_ubuf = &io_notif_to_data(zc->notif)->uarg;
-       msg.sg_from_iter = io_sg_from_iter;
        ret = sock_sendmsg(sock, &msg);
 
        if (unlikely(ret < min_ret)) {