mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	io_uring: add support for sendmsg()
This is done through IORING_OP_SENDMSG. There's a new sqe->msg_flags for the flags argument, and the msghdr struct is passed in the sqe->addr field. We use MSG_DONTWAIT to force an inline fast path if sendmsg() 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>
This commit is contained in:
		
							parent
							
								
									9e645e1105
								
							
						
					
					
						commit
						0fa03c624d
					
				
					 4 changed files with 53 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1390,6 +1390,43 @@ static int io_sync_file_range(struct io_kiocb *req,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 | 
			
		||||
		      bool force_nonblock)
 | 
			
		||||
{
 | 
			
		||||
#if defined(CONFIG_NET)
 | 
			
		||||
	struct socket *sock;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	sock = sock_from_file(req->file, &ret);
 | 
			
		||||
	if (sock) {
 | 
			
		||||
		struct user_msghdr __user *msg;
 | 
			
		||||
		unsigned flags;
 | 
			
		||||
 | 
			
		||||
		flags = READ_ONCE(sqe->msg_flags);
 | 
			
		||||
		if (flags & MSG_DONTWAIT)
 | 
			
		||||
			req->flags |= REQ_F_NOWAIT;
 | 
			
		||||
		else if (force_nonblock)
 | 
			
		||||
			flags |= MSG_DONTWAIT;
 | 
			
		||||
 | 
			
		||||
		msg = (struct user_msghdr __user *) (unsigned long)
 | 
			
		||||
			READ_ONCE(sqe->addr);
 | 
			
		||||
 | 
			
		||||
		ret = __sys_sendmsg_sock(sock, msg, flags);
 | 
			
		||||
		if (force_nonblock && ret == -EAGAIN)
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	io_cqring_add_event(req->ctx, sqe->user_data, ret);
 | 
			
		||||
	io_put_req(req);
 | 
			
		||||
	return 0;
 | 
			
		||||
#else
 | 
			
		||||
	return -EOPNOTSUPP;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void io_poll_remove_one(struct io_kiocb *req)
 | 
			
		||||
{
 | 
			
		||||
	struct io_poll_iocb *poll = &req->poll;
 | 
			
		||||
| 
						 | 
				
			
			@ -1675,6 +1712,9 @@ static int __io_submit_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 | 
			
		|||
	case IORING_OP_SYNC_FILE_RANGE:
 | 
			
		||||
		ret = io_sync_file_range(req, s->sqe, force_nonblock);
 | 
			
		||||
		break;
 | 
			
		||||
	case IORING_OP_SENDMSG:
 | 
			
		||||
		ret = io_sendmsg(req, s->sqe, force_nonblock);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
 | 
			
		||||
struct pid;
 | 
			
		||||
struct cred;
 | 
			
		||||
struct socket;
 | 
			
		||||
 | 
			
		||||
#define __sockaddr_check_size(size)	\
 | 
			
		||||
	BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
 | 
			
		||||
| 
						 | 
				
			
			@ -374,6 +375,9 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
 | 
			
		|||
extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
 | 
			
		||||
			  unsigned int vlen, unsigned int flags,
 | 
			
		||||
			  bool forbid_cmsg_compat);
 | 
			
		||||
extern long __sys_sendmsg_sock(struct socket *sock,
 | 
			
		||||
			       struct user_msghdr __user *msg,
 | 
			
		||||
			       unsigned int flags);
 | 
			
		||||
 | 
			
		||||
/* helpers which do the actual work for syscalls */
 | 
			
		||||
extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ struct io_uring_sqe {
 | 
			
		|||
		__u32		fsync_flags;
 | 
			
		||||
		__u16		poll_events;
 | 
			
		||||
		__u32		sync_range_flags;
 | 
			
		||||
		__u32		msg_flags;
 | 
			
		||||
	};
 | 
			
		||||
	__u64	user_data;	/* data to be passed back at completion time */
 | 
			
		||||
	union {
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +59,7 @@ struct io_uring_sqe {
 | 
			
		|||
#define IORING_OP_POLL_ADD	6
 | 
			
		||||
#define IORING_OP_POLL_REMOVE	7
 | 
			
		||||
#define IORING_OP_SYNC_FILE_RANGE	8
 | 
			
		||||
#define IORING_OP_SENDMSG	9
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sqe->fsync_flags
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2313,6 +2313,13 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
 | 
			
		|||
/*
 | 
			
		||||
 *	BSD sendmsg interface
 | 
			
		||||
 */
 | 
			
		||||
long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
 | 
			
		||||
			unsigned int flags)
 | 
			
		||||
{
 | 
			
		||||
	struct msghdr msg_sys;
 | 
			
		||||
 | 
			
		||||
	return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
 | 
			
		||||
		   bool forbid_cmsg_compat)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue