mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 00:28:52 +02:00 
			
		
		
		
	 91db6edc57
			
		
	
	
		91db6edc57
		
	
	
	
	
		
			
			We keep socket io_uring command implementation in io_uring/uring_cmd.c. Separate it from generic command code into a separate file. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/747d0519a2255bd055ae76b691d38d2b4c311001.1745843119.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
		
			
				
	
	
		
			83 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <asm/ioctls.h>
 | |
| #include <linux/io_uring/net.h>
 | |
| #include <net/sock.h>
 | |
| 
 | |
| #include "uring_cmd.h"
 | |
| 
 | |
| static inline int io_uring_cmd_getsockopt(struct socket *sock,
 | |
| 					  struct io_uring_cmd *cmd,
 | |
| 					  unsigned int issue_flags)
 | |
| {
 | |
| 	const struct io_uring_sqe *sqe = cmd->sqe;
 | |
| 	bool compat = !!(issue_flags & IO_URING_F_COMPAT);
 | |
| 	int optlen, optname, level, err;
 | |
| 	void __user *optval;
 | |
| 
 | |
| 	level = READ_ONCE(sqe->level);
 | |
| 	if (level != SOL_SOCKET)
 | |
| 		return -EOPNOTSUPP;
 | |
| 
 | |
| 	optval = u64_to_user_ptr(READ_ONCE(sqe->optval));
 | |
| 	optname = READ_ONCE(sqe->optname);
 | |
| 	optlen = READ_ONCE(sqe->optlen);
 | |
| 
 | |
| 	err = do_sock_getsockopt(sock, compat, level, optname,
 | |
| 				 USER_SOCKPTR(optval),
 | |
| 				 KERNEL_SOCKPTR(&optlen));
 | |
| 	if (err)
 | |
| 		return err;
 | |
| 
 | |
| 	/* On success, return optlen */
 | |
| 	return optlen;
 | |
| }
 | |
| 
 | |
| static inline int io_uring_cmd_setsockopt(struct socket *sock,
 | |
| 					  struct io_uring_cmd *cmd,
 | |
| 					  unsigned int issue_flags)
 | |
| {
 | |
| 	const struct io_uring_sqe *sqe = cmd->sqe;
 | |
| 	bool compat = !!(issue_flags & IO_URING_F_COMPAT);
 | |
| 	int optname, optlen, level;
 | |
| 	void __user *optval;
 | |
| 	sockptr_t optval_s;
 | |
| 
 | |
| 	optval = u64_to_user_ptr(READ_ONCE(sqe->optval));
 | |
| 	optname = READ_ONCE(sqe->optname);
 | |
| 	optlen = READ_ONCE(sqe->optlen);
 | |
| 	level = READ_ONCE(sqe->level);
 | |
| 	optval_s = USER_SOCKPTR(optval);
 | |
| 
 | |
| 	return do_sock_setsockopt(sock, compat, level, optname, optval_s,
 | |
| 				  optlen);
 | |
| }
 | |
| 
 | |
| int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags)
 | |
| {
 | |
| 	struct socket *sock = cmd->file->private_data;
 | |
| 	struct sock *sk = sock->sk;
 | |
| 	struct proto *prot = READ_ONCE(sk->sk_prot);
 | |
| 	int ret, arg = 0;
 | |
| 
 | |
| 	if (!prot || !prot->ioctl)
 | |
| 		return -EOPNOTSUPP;
 | |
| 
 | |
| 	switch (cmd->cmd_op) {
 | |
| 	case SOCKET_URING_OP_SIOCINQ:
 | |
| 		ret = prot->ioctl(sk, SIOCINQ, &arg);
 | |
| 		if (ret)
 | |
| 			return ret;
 | |
| 		return arg;
 | |
| 	case SOCKET_URING_OP_SIOCOUTQ:
 | |
| 		ret = prot->ioctl(sk, SIOCOUTQ, &arg);
 | |
| 		if (ret)
 | |
| 			return ret;
 | |
| 		return arg;
 | |
| 	case SOCKET_URING_OP_GETSOCKOPT:
 | |
| 		return io_uring_cmd_getsockopt(sock, cmd, issue_flags);
 | |
| 	case SOCKET_URING_OP_SETSOCKOPT:
 | |
| 		return io_uring_cmd_setsockopt(sock, cmd, issue_flags);
 | |
| 	default:
 | |
| 		return -EOPNOTSUPP;
 | |
| 	}
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(io_uring_cmd_sock);
 |