diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-04-19 15:38:09 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-07-09 16:32:14 -0400 |
commit | aa1fa28fc73ea6b740ee7b62bf3b07141883dbb8 (patch) | |
tree | 85963ae2cf72deda9bea41efd9492c94e9344b8b | |
parent | 0fa03c624d8fc9932d0f27c39a9deca6a37e0e17 (diff) |
io_uring: add support for recvmsg()
This is done through IORING_OP_RECVMSG. This opcode uses the same
sqe->msg_flags that IORING_OP_SENDMSG added, and we pass in the
msghdr struct in the sqe->addr field as well.
We use MSG_DONTWAIT to force an inline fast path if recvmsg() doesn't
block, and punt to async execution if it would have.
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | fs/io_uring.c | 31 | ||||
-rw-r--r-- | include/linux/socket.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/io_uring.h | 1 | ||||
-rw-r--r-- | net/socket.c | 8 |
4 files changed, 39 insertions, 4 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 5d4cd8c4132d..8d86e31b0762 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c | |||
@@ -1390,10 +1390,12 @@ static int io_sync_file_range(struct io_kiocb *req, | |||
1390 | return 0; | 1390 | return 0; |
1391 | } | 1391 | } |
1392 | 1392 | ||
1393 | static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | ||
1394 | bool force_nonblock) | ||
1395 | { | ||
1396 | #if defined(CONFIG_NET) | 1393 | #if defined(CONFIG_NET) |
1394 | static int io_send_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | ||
1395 | bool force_nonblock, | ||
1396 | long (*fn)(struct socket *, struct user_msghdr __user *, | ||
1397 | unsigned int)) | ||
1398 | { | ||
1397 | struct socket *sock; | 1399 | struct socket *sock; |
1398 | int ret; | 1400 | int ret; |
1399 | 1401 | ||
@@ -1414,7 +1416,7 @@ static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | |||
1414 | msg = (struct user_msghdr __user *) (unsigned long) | 1416 | msg = (struct user_msghdr __user *) (unsigned long) |
1415 | READ_ONCE(sqe->addr); | 1417 | READ_ONCE(sqe->addr); |
1416 | 1418 | ||
1417 | ret = __sys_sendmsg_sock(sock, msg, flags); | 1419 | ret = fn(sock, msg, flags); |
1418 | if (force_nonblock && ret == -EAGAIN) | 1420 | if (force_nonblock && ret == -EAGAIN) |
1419 | return ret; | 1421 | return ret; |
1420 | } | 1422 | } |
@@ -1422,6 +1424,24 @@ static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | |||
1422 | io_cqring_add_event(req->ctx, sqe->user_data, ret); | 1424 | io_cqring_add_event(req->ctx, sqe->user_data, ret); |
1423 | io_put_req(req); | 1425 | io_put_req(req); |
1424 | return 0; | 1426 | return 0; |
1427 | } | ||
1428 | #endif | ||
1429 | |||
1430 | static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | ||
1431 | bool force_nonblock) | ||
1432 | { | ||
1433 | #if defined(CONFIG_NET) | ||
1434 | return io_send_recvmsg(req, sqe, force_nonblock, __sys_sendmsg_sock); | ||
1435 | #else | ||
1436 | return -EOPNOTSUPP; | ||
1437 | #endif | ||
1438 | } | ||
1439 | |||
1440 | static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe, | ||
1441 | bool force_nonblock) | ||
1442 | { | ||
1443 | #if defined(CONFIG_NET) | ||
1444 | return io_send_recvmsg(req, sqe, force_nonblock, __sys_recvmsg_sock); | ||
1425 | #else | 1445 | #else |
1426 | return -EOPNOTSUPP; | 1446 | return -EOPNOTSUPP; |
1427 | #endif | 1447 | #endif |
@@ -1715,6 +1735,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req, | |||
1715 | case IORING_OP_SENDMSG: | 1735 | case IORING_OP_SENDMSG: |
1716 | ret = io_sendmsg(req, s->sqe, force_nonblock); | 1736 | ret = io_sendmsg(req, s->sqe, force_nonblock); |
1717 | break; | 1737 | break; |
1738 | case IORING_OP_RECVMSG: | ||
1739 | ret = io_recvmsg(req, s->sqe, force_nonblock); | ||
1740 | break; | ||
1718 | default: | 1741 | default: |
1719 | ret = -EINVAL; | 1742 | ret = -EINVAL; |
1720 | break; | 1743 | break; |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 9d770ef3ced5..97523818cb14 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -378,6 +378,9 @@ extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, | |||
378 | extern long __sys_sendmsg_sock(struct socket *sock, | 378 | extern long __sys_sendmsg_sock(struct socket *sock, |
379 | struct user_msghdr __user *msg, | 379 | struct user_msghdr __user *msg, |
380 | unsigned int flags); | 380 | unsigned int flags); |
381 | extern long __sys_recvmsg_sock(struct socket *sock, | ||
382 | struct user_msghdr __user *msg, | ||
383 | unsigned int flags); | ||
381 | 384 | ||
382 | /* helpers which do the actual work for syscalls */ | 385 | /* helpers which do the actual work for syscalls */ |
383 | extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, | 386 | extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, |
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h index d74742d6269f..1e1652f25cc1 100644 --- a/include/uapi/linux/io_uring.h +++ b/include/uapi/linux/io_uring.h | |||
@@ -60,6 +60,7 @@ struct io_uring_sqe { | |||
60 | #define IORING_OP_POLL_REMOVE 7 | 60 | #define IORING_OP_POLL_REMOVE 7 |
61 | #define IORING_OP_SYNC_FILE_RANGE 8 | 61 | #define IORING_OP_SYNC_FILE_RANGE 8 |
62 | #define IORING_OP_SENDMSG 9 | 62 | #define IORING_OP_SENDMSG 9 |
63 | #define IORING_OP_RECVMSG 10 | ||
63 | 64 | ||
64 | /* | 65 | /* |
65 | * sqe->fsync_flags | 66 | * sqe->fsync_flags |
diff --git a/net/socket.c b/net/socket.c index b9536940255e..98354cc18840 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2494,6 +2494,14 @@ out_freeiov: | |||
2494 | * BSD recvmsg interface | 2494 | * BSD recvmsg interface |
2495 | */ | 2495 | */ |
2496 | 2496 | ||
2497 | long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg, | ||
2498 | unsigned int flags) | ||
2499 | { | ||
2500 | struct msghdr msg_sys; | ||
2501 | |||
2502 | return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); | ||
2503 | } | ||
2504 | |||
2497 | long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, | 2505 | long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, |
2498 | bool forbid_cmsg_compat) | 2506 | bool forbid_cmsg_compat) |
2499 | { | 2507 | { |