diff mbox series

[v6,6/8] io_uring/cmd: Introduce SOCKET_URING_OP_GETSOCKOPT

Message ID 20230913152744.2333228-7-leitao@debian.org (mailing list archive)
State Not Applicable
Headers show
Series io_uring: Initial support for {s,g}etsockopt commands | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-0 success Logs for ${{ matrix.test }} on ${{ matrix.arch }} with ${{ matrix.toolchain_full }}
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 fail Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 fail Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 fail Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for veristat
bpf/vmtest-bpf-next-VM_Test-6 success Logs for set-matrix
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Guessed tree name to be net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1539 this patch: 1539
netdev/cc_maintainers success CCed 4 of 4 maintainers
netdev/build_clang success Errors and warnings before: 1377 this patch: 1377
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1571 this patch: 1571
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 54 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline fail Was 0 now: 1

Commit Message

Breno Leitao Sept. 13, 2023, 3:27 p.m. UTC
Add support for getsockopt command (SOCKET_URING_OP_GETSOCKOPT), where
level is SOL_SOCKET. This is similar to the getsockopt(2) system
call, and both parameters are pointers to userspace.

Important to say that userspace needs to keep the pointer alive until
the CQE is completed.

Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Breno Leitao <leitao@debian.org>
---
 include/uapi/linux/io_uring.h |  9 +++++++++
 io_uring/uring_cmd.c          | 15 +++++++++++++++
 2 files changed, 24 insertions(+)

Comments

Jens Axboe Sept. 13, 2023, 7:36 p.m. UTC | #1
On 9/13/23 9:27 AM, Breno Leitao wrote:
> Add support for getsockopt command (SOCKET_URING_OP_GETSOCKOPT), where
> level is SOL_SOCKET. This is similar to the getsockopt(2) system
> call, and both parameters are pointers to userspace.
> 
> Important to say that userspace needs to keep the pointer alive until
> the CQE is completed.

Since it's holding the data needed, this is true for any request that
is writing data. IOW, this is not unusual and should be taken for
granted. I think this may warrant a bit of rewording if the patch is
respun, if not then just ignore it.

> diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
> index 5753c3611b74..a2a6ac0c503b 100644
> --- a/io_uring/uring_cmd.c
> +++ b/io_uring/uring_cmd.c
> @@ -167,6 +167,19 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
>  }
>  EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
>  
> +static inline int io_uring_cmd_getsockopt(struct socket *sock,
> +					  struct io_uring_cmd *cmd,
> +					  unsigned int issue_flags)
> +{
> +	void __user *optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval));
> +	int __user *optlen = u64_to_user_ptr(READ_ONCE(cmd->sqe->optlen));
> +	bool compat = !!(issue_flags & IO_URING_F_COMPAT);
> +	int optname = READ_ONCE(cmd->sqe->optname);
> +	int level = READ_ONCE(cmd->sqe->level);
> +
> +	return do_sock_getsockopt(sock, compat, level, optname, optval, optlen);
> +}

Personal preference, but any other io_uring generally uses the format
of:

	bool compat = !!(issue_flags & IO_URING_F_COMPAT);
	void __user *optval;
	int __user *optlen;
	int optname, level;

	optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval));
	optlen = u64_to_user_ptr(READ_ONCE(cmd->sqe->optlen));
	optname = READ_ONCE(cmd->sqe->optname);
	level = READ_ONCE(cmd->sqe->level);

	return do_sock_getsockopt(sock, compat, level, optname, optval, optlen);

which I find a lot easier to read than bundling variable declarations
and reading the values into them.

And I always forget that cmd->sqe is a copy for URING_CMD, which makes
this just look wrong as they should've been read at prep time rather
than issue time. But it's fine!
Jens Axboe Sept. 13, 2023, 7:37 p.m. UTC | #2
On 9/13/23 1:36 PM, Jens Axboe wrote:
> On 9/13/23 9:27 AM, Breno Leitao wrote:
>> Add support for getsockopt command (SOCKET_URING_OP_GETSOCKOPT), where
>> level is SOL_SOCKET. This is similar to the getsockopt(2) system
>> call, and both parameters are pointers to userspace.
>>
>> Important to say that userspace needs to keep the pointer alive until
>> the CQE is completed.
> 
> Since it's holding the data needed, this is true for any request that
> is writing data. IOW, this is not unusual and should be taken for
> granted. I think this may warrant a bit of rewording if the patch is
> respun, if not then just ignore it.

reads data of course, writing into the userspace buffer.
diff mbox series

Patch

diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 8e61f8b7c2ce..1c789ee6462d 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -43,6 +43,10 @@  struct io_uring_sqe {
 	union {
 		__u64	addr;	/* pointer to buffer or iovecs */
 		__u64	splice_off_in;
+		struct {
+			__u32	level;
+			__u32	optname;
+		};
 	};
 	__u32	len;		/* buffer size or number of iovecs */
 	union {
@@ -89,6 +93,10 @@  struct io_uring_sqe {
 			__u64	addr3;
 			__u64	__pad2[1];
 		};
+		struct {
+			__u64	optval;
+			__u64	optlen;
+		};
 		/*
 		 * If the ring is initialized with IORING_SETUP_SQE128, then
 		 * this field is used for 80 bytes of arbitrary command data
@@ -734,6 +742,7 @@  struct io_uring_recvmsg_out {
 enum {
 	SOCKET_URING_OP_SIOCINQ		= 0,
 	SOCKET_URING_OP_SIOCOUTQ,
+	SOCKET_URING_OP_GETSOCKOPT,
 };
 
 #ifdef __cplusplus
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index 5753c3611b74..a2a6ac0c503b 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -167,6 +167,19 @@  int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
 }
 EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
 
+static inline int io_uring_cmd_getsockopt(struct socket *sock,
+					  struct io_uring_cmd *cmd,
+					  unsigned int issue_flags)
+{
+	void __user *optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval));
+	int __user *optlen = u64_to_user_ptr(READ_ONCE(cmd->sqe->optlen));
+	bool compat = !!(issue_flags & IO_URING_F_COMPAT);
+	int optname = READ_ONCE(cmd->sqe->optname);
+	int level = READ_ONCE(cmd->sqe->level);
+
+	return do_sock_getsockopt(sock, compat, level, optname, optval, optlen);
+}
+
 #if defined(CONFIG_NET)
 int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags)
 {
@@ -189,6 +202,8 @@  int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags)
 		if (ret)
 			return ret;
 		return arg;
+	case SOCKET_URING_OP_GETSOCKOPT:
+		return io_uring_cmd_getsockopt(sock, cmd, issue_flags);
 	default:
 		return -EOPNOTSUPP;
 	}