From: Jens Axboe <[email protected]>
To: [email protected]
Cc: [email protected], Jens Axboe <[email protected]>
Subject: [PATCH 4/5] io_uring: ensure async punted connect requests copy data
Date: Mon, 2 Dec 2019 19:54:43 -0700 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
Just like commit bd26dacbd5ce for read/write requests, this one ensures
that the sockaddr data has been copied for IORING_OP_CONNECT if we need
to punt the request to async context.
Signed-off-by: Jens Axboe <[email protected]>
---
fs/io_uring.c | 47 ++++++++++++++++++++++++++++++++++++++----
include/linux/socket.h | 5 ++---
net/socket.c | 16 +++++++-------
3 files changed, 53 insertions(+), 15 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 11d181ed2076..d5cd338ac8bf 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -308,6 +308,10 @@ struct io_timeout {
struct io_timeout_data *data;
};
+struct io_async_connect {
+ struct sockaddr_storage address;
+};
+
struct io_async_msghdr {
struct iovec fast_iov[UIO_FASTIOV];
struct iovec *iov;
@@ -327,6 +331,7 @@ struct io_async_ctx {
union {
struct io_async_rw rw;
struct io_async_msghdr msg;
+ struct io_async_connect connect;
};
};
@@ -2187,11 +2192,22 @@ static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe,
#endif
}
+static int io_connect_prep(struct io_kiocb *req, struct io_async_ctx *io)
+{
+ const struct io_uring_sqe *sqe = req->sqe;
+ struct sockaddr __user *addr;
+ int addr_len;
+
+ addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
+ addr_len = READ_ONCE(sqe->addr2);
+ return move_addr_to_kernel(addr, addr_len, &io->connect.address);
+}
+
static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
struct io_kiocb **nxt, bool force_nonblock)
{
#if defined(CONFIG_NET)
- struct sockaddr __user *addr;
+ struct io_async_ctx __io, *io;
unsigned file_flags;
int addr_len, ret;
@@ -2200,15 +2216,35 @@ static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)
return -EINVAL;
- addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
addr_len = READ_ONCE(sqe->addr2);
file_flags = force_nonblock ? O_NONBLOCK : 0;
- ret = __sys_connect_file(req->file, addr, addr_len, file_flags);
- if (ret == -EAGAIN && force_nonblock)
+ if (req->io) {
+ io = req->io;
+ } else {
+ ret = io_connect_prep(req, &__io);
+ if (ret)
+ goto out;
+ io = &__io;
+ }
+
+ ret = __sys_connect_file(req->file, &io->connect.address, addr_len,
+ file_flags);
+ if (ret == -EAGAIN && force_nonblock) {
+ io = kmalloc(sizeof(*io), GFP_KERNEL);
+ if (!io) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memcpy(&io->connect, &__io.connect, sizeof(io->connect));
+ req->io = io;
+ memcpy(&io->sqe, req->sqe, sizeof(*req->sqe));
+ req->sqe = &io->sqe;
return -EAGAIN;
+ }
if (ret == -ERESTARTSYS)
ret = -EINTR;
+out:
if (ret < 0 && (req->flags & REQ_F_LINK))
req->flags |= REQ_F_FAIL_LINK;
io_cqring_add_event(req, ret);
@@ -2822,6 +2858,9 @@ static int io_req_defer_prep(struct io_kiocb *req, struct io_async_ctx *io)
case IORING_OP_RECVMSG:
ret = io_recvmsg_prep(req, io);
break;
+ case IORING_OP_CONNECT:
+ ret = io_connect_prep(req, io);
+ break;
default:
req->io = io;
return 0;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 903507fb901f..2d2313403101 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -406,9 +406,8 @@ extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags);
extern int __sys_socket(int family, int type, int protocol);
extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
-extern int __sys_connect_file(struct file *file,
- struct sockaddr __user *uservaddr, int addrlen,
- int file_flags);
+extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
+ int addrlen, int file_flags);
extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
int addrlen);
extern int __sys_listen(int fd, int backlog);
diff --git a/net/socket.c b/net/socket.c
index 0fb0820edeec..b343db1489bd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1826,26 +1826,22 @@ SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
* include the -EINPROGRESS status for such sockets.
*/
-int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr,
+int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
int addrlen, int file_flags)
{
struct socket *sock;
- struct sockaddr_storage address;
int err;
sock = sock_from_file(file, &err);
if (!sock)
goto out;
- err = move_addr_to_kernel(uservaddr, addrlen, &address);
- if (err < 0)
- goto out;
err =
- security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
+ security_socket_connect(sock, (struct sockaddr *)address, addrlen);
if (err)
goto out;
- err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
+ err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
sock->file->f_flags | file_flags);
out:
return err;
@@ -1858,7 +1854,11 @@ int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
f = fdget(fd);
if (f.file) {
- ret = __sys_connect_file(f.file, uservaddr, addrlen, 0);
+ struct sockaddr_storage address;
+
+ ret = move_addr_to_kernel(uservaddr, addrlen, &address);
+ if (!ret)
+ ret = __sys_connect_file(f.file, &address, addrlen, 0);
if (f.flags)
fput(f.file);
}
--
2.24.0
next prev parent reply other threads:[~2019-12-03 2:55 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-03 2:54 [PATCHSET v2 0/5] io_uring: ensure all needed read/write data is stable Jens Axboe
2019-12-03 2:54 ` [PATCH 1/5] io_uring: add general async offload context Jens Axboe
2019-12-03 2:54 ` [PATCH 2/5] io_uring: ensure async punted read/write requests copy iovec Jens Axboe
2019-12-03 2:54 ` [PATCH 3/5] io_uring: ensure async punted sendmsg/recvmsg requests copy data Jens Axboe
2019-12-03 2:54 ` Jens Axboe [this message]
2019-12-03 2:54 ` [PATCH 5/5] io_uring: mark us with IORING_FEAT_SUBMIT_STABLE Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox