Skip to content

Commit 581711c

Browse files
isilenceaxboe
authored andcommitted
io_uring/net: save address for sendzc async execution
We usually copy all bits that a request needs from the userspace for async execution, so the userspace can keep them on the stack. However, send zerocopy violates this pattern for addresses and may reloads it e.g. from io-wq. Save the address if any in ->async_data as usual. Reported-by: Stefan Metzmacher <[email protected]> Signed-off-by: Pavel Begunkov <[email protected]> Link: https://lore.kernel.org/r/d7512d7aa9abcd36e9afe1a4d292a24cb2d157e5.1661342812.git.asml.silence@gmail.com [axboe: fold in incremental fix] Signed-off-by: Jens Axboe <[email protected]>
1 parent 5916943 commit 581711c

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

io_uring/net.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,37 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
182182
&iomsg->free_iov);
183183
}
184184

185+
int io_sendzc_prep_async(struct io_kiocb *req)
186+
{
187+
struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
188+
struct io_async_msghdr *io;
189+
int ret;
190+
191+
if (!zc->addr || req_has_async_data(req))
192+
return 0;
193+
if (io_alloc_async_data(req))
194+
return -ENOMEM;
195+
196+
io = req->async_data;
197+
ret = move_addr_to_kernel(zc->addr, zc->addr_len, &io->addr);
198+
return ret;
199+
}
200+
201+
static int io_setup_async_addr(struct io_kiocb *req,
202+
struct sockaddr_storage *addr,
203+
unsigned int issue_flags)
204+
{
205+
struct io_async_msghdr *io;
206+
207+
if (!addr || req_has_async_data(req))
208+
return -EAGAIN;
209+
if (io_alloc_async_data(req))
210+
return -ENOMEM;
211+
io = req->async_data;
212+
memcpy(&io->addr, addr, sizeof(io->addr));
213+
return -EAGAIN;
214+
}
215+
185216
int io_sendmsg_prep_async(struct io_kiocb *req)
186217
{
187218
int ret;
@@ -944,7 +975,7 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
944975

945976
int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
946977
{
947-
struct sockaddr_storage address;
978+
struct sockaddr_storage __address, *addr = NULL;
948979
struct io_ring_ctx *ctx = req->ctx;
949980
struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
950981
struct io_notif_slot *notif_slot;
@@ -978,10 +1009,17 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
9781009
msg.msg_namelen = 0;
9791010

9801011
if (zc->addr) {
981-
ret = move_addr_to_kernel(zc->addr, zc->addr_len, &address);
982-
if (unlikely(ret < 0))
983-
return ret;
984-
msg.msg_name = (struct sockaddr *)&address;
1012+
if (req_has_async_data(req)) {
1013+
struct io_async_msghdr *io = req->async_data;
1014+
1015+
msg.msg_name = addr = &io->addr;
1016+
} else {
1017+
ret = move_addr_to_kernel(zc->addr, zc->addr_len, &__address);
1018+
if (unlikely(ret < 0))
1019+
return ret;
1020+
msg.msg_name = (struct sockaddr *)&__address;
1021+
addr = &__address;
1022+
}
9851023
msg.msg_namelen = zc->addr_len;
9861024
}
9871025

@@ -1013,13 +1051,14 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
10131051

10141052
if (unlikely(ret < min_ret)) {
10151053
if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
1016-
return -EAGAIN;
1054+
return io_setup_async_addr(req, addr, issue_flags);
1055+
10171056
if (ret > 0 && io_net_retry(sock, msg.msg_flags)) {
10181057
zc->len -= ret;
10191058
zc->buf += ret;
10201059
zc->done_io += ret;
10211060
req->flags |= REQ_F_PARTIAL_IO;
1022-
return -EAGAIN;
1061+
return io_setup_async_addr(req, addr, issue_flags);
10231062
}
10241063
if (ret == -ERESTARTSYS)
10251064
ret = -EINTR;

io_uring/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct io_async_connect {
3131
int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
3232
int io_shutdown(struct io_kiocb *req, unsigned int issue_flags);
3333

34+
int io_sendzc_prep_async(struct io_kiocb *req);
3435
int io_sendmsg_prep_async(struct io_kiocb *req);
3536
void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req);
3637
int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);

io_uring/opdef.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,13 +478,15 @@ const struct io_op_def io_op_defs[] = {
478478
.pollout = 1,
479479
.audit_skip = 1,
480480
.ioprio = 1,
481+
.manual_alloc = 1,
481482
#if defined(CONFIG_NET)
483+
.async_size = sizeof(struct io_async_msghdr),
482484
.prep = io_sendzc_prep,
483485
.issue = io_sendzc,
486+
.prep_async = io_sendzc_prep_async,
484487
#else
485488
.prep = io_eopnotsupp_prep,
486489
#endif
487-
488490
},
489491
};
490492

0 commit comments

Comments
 (0)