From: Jens Axboe <[email protected]>
To: Norman Maurer <[email protected]>, [email protected]
Subject: Re: Support for shutdown
Date: Sat, 5 Sep 2020 11:11:10 -0600 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
On 9/5/20 11:03 AM, Norman Maurer wrote:
> Hi there,
>
> As you may have noticed from previous emails we are currently writing
> a new transport for netty that will use io_uring under the hood for
> max performance. One thing that is missing at the moment is the
> support for “shutdown”. Shutdown is quite useful in TCP land when you
> only want to close either input or output of the connection.
>
> Is this something you think that can be added in the future ? This
> would be a perfect addition to the already existing close support.
Something like this should do it, should just be split into having the
net part as a prep patch. I can add this to the 5.8 branch if that's
easier for you to test?
diff --git a/fs/io_uring.c b/fs/io_uring.c
index a9a625ceea5f..67714078e85d 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -529,6 +529,11 @@ struct io_statx {
struct statx __user *buffer;
};
+struct io_shutdown {
+ struct file *file;
+ int how;
+};
+
struct io_completion {
struct file *file;
struct list_head list;
@@ -666,6 +671,7 @@ struct io_kiocb {
struct io_splice splice;
struct io_provide_buf pbuf;
struct io_statx statx;
+ struct io_shutdown shutdown;
/* use only after cleaning per-op data, see io_clean_op() */
struct io_completion compl;
};
@@ -922,6 +928,9 @@ static const struct io_op_def io_op_defs[] __read_mostly = {
.hash_reg_file = 1,
.unbound_nonreg_file = 1,
},
+ [IORING_OP_SHUTDOWN] = {
+ .needs_file = 1,
+ },
};
enum io_mem_account {
@@ -3367,6 +3376,44 @@ static int io_write(struct io_kiocb *req, bool force_nonblock,
return ret;
}
+static int io_shutdown_prep(struct io_kiocb *req,
+ const struct io_uring_sqe *sqe)
+{
+#if defined(CONFIG_NET)
+ if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
+ return -EINVAL;
+ if (sqe->ioprio || sqe->off || sqe->addr || sqe->len ||
+ sqe->rw_flags || sqe->buf_index)
+ return -EINVAL;
+
+ req->shutdown.how = READ_ONCE(sqe->len);
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
+static int io_shutdown(struct io_kiocb *req, bool force_nonblock)
+{
+#if defined(CONFIG_NET)
+ struct socket *sock;
+ int ret;
+
+ if (force_nonblock)
+ return -EAGAIN;
+
+ sock = sock_from_file(req->file, &ret);
+ if (unlikely(!sock))
+ return ret;
+
+ ret = __sys_shutdown_sock(sock, req->shutdown.how);
+ io_req_complete(req, ret);
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
static int __io_splice_prep(struct io_kiocb *req,
const struct io_uring_sqe *sqe)
{
@@ -5588,6 +5635,9 @@ static int io_req_defer_prep(struct io_kiocb *req,
case IORING_OP_TEE:
ret = io_tee_prep(req, sqe);
break;
+ case IORING_OP_SHUTDOWN:
+ ret = io_shutdown_prep(req, sqe);
+ break;
default:
printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n",
req->opcode);
@@ -5942,6 +5992,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
}
ret = io_tee(req, force_nonblock);
break;
+ case IORING_OP_SHUTDOWN:
+ if (req) {
+ ret = io_shutdown_prep(req, sqe);
+ if (ret < 0)
+ break;
+ }
+ ret = io_shutdown(req, force_nonblock);
+ break;
default:
ret = -EINVAL;
break;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index e9cb30d8cbfb..385894b4a8bb 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -436,6 +436,7 @@ extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
int __user *usockaddr_len);
extern int __sys_socketpair(int family, int type, int protocol,
int __user *usockvec);
+extern int __sys_shutdown_sock(struct socket *sock, int how);
extern int __sys_shutdown(int fd, int how);
extern struct ns_common *get_net_ns(struct ns_common *ns);
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 7539d912690b..2301c37e86cb 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -132,6 +132,7 @@ enum {
IORING_OP_PROVIDE_BUFFERS,
IORING_OP_REMOVE_BUFFERS,
IORING_OP_TEE,
+ IORING_OP_SHUTDOWN,
/* this goes last, obviously */
IORING_OP_LAST,
diff --git a/net/socket.c b/net/socket.c
index 0c0144604f81..8616962c27bc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2192,6 +2192,17 @@ SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
* Shutdown a socket.
*/
+int __sys_shutdown_sock(struct socket *sock, int how)
+{
+ int err;
+
+ err = security_socket_shutdown(sock, how);
+ if (!err)
+ err = sock->ops->shutdown(sock, how);
+
+ return err;
+}
+
int __sys_shutdown(int fd, int how)
{
int err, fput_needed;
@@ -2199,9 +2210,7 @@ int __sys_shutdown(int fd, int how)
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock != NULL) {
- err = security_socket_shutdown(sock, how);
- if (!err)
- err = sock->ops->shutdown(sock, how);
+ err = __sys_shutdown_sock(sock, how);
fput_light(sock->file, fput_needed);
}
return err;
--
Jens Axboe
next prev parent reply other threads:[~2020-09-05 17:11 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-05 17:03 Support for shutdown Norman Maurer
2020-09-05 17:11 ` Jens Axboe [this message]
2020-09-05 17:12 ` Norman Maurer
2020-09-05 17:13 ` 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