diff options
Diffstat (limited to 'io_uring/net.c')
| -rw-r--r-- | io_uring/net.c | 68 | 
1 files changed, 40 insertions, 28 deletions
diff --git a/io_uring/net.c b/io_uring/net.c index 0af8a02df580..60e392f7f2dc 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -65,12 +65,12 @@ struct io_sendzc {  	struct file			*file;  	void __user			*buf;  	size_t				len; -	u16				slot_idx;  	unsigned			msg_flags;  	unsigned			flags;  	unsigned			addr_len;  	void __user			*addr;  	size_t				done_io; +	struct io_kiocb 		*notif;  };  #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED) @@ -879,18 +879,39 @@ out_free:  	return ret;  } +void io_sendzc_cleanup(struct io_kiocb *req) +{ +	struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc); + +	zc->notif->flags |= REQ_F_CQE_SKIP; +	io_notif_flush(zc->notif); +	zc->notif = NULL; +} +  int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)  {  	struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);  	struct io_ring_ctx *ctx = req->ctx; +	struct io_kiocb *notif; -	if (READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3)) +	if (READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3) || +	    READ_ONCE(sqe->__pad3[0])) +		return -EINVAL; +	/* we don't support IOSQE_CQE_SKIP_SUCCESS just yet */ +	if (req->flags & REQ_F_CQE_SKIP)  		return -EINVAL;  	zc->flags = READ_ONCE(sqe->ioprio);  	if (zc->flags & ~(IORING_RECVSEND_POLL_FIRST | -			  IORING_RECVSEND_FIXED_BUF | IORING_RECVSEND_NOTIF_FLUSH)) +			  IORING_RECVSEND_FIXED_BUF))  		return -EINVAL; +	notif = zc->notif = io_alloc_notif(ctx); +	if (!notif) +		return -ENOMEM; +	notif->cqe.user_data = req->cqe.user_data; +	notif->cqe.res = 0; +	notif->cqe.flags = IORING_CQE_F_NOTIF; +	req->flags |= REQ_F_NEED_CLEANUP;  	if (zc->flags & IORING_RECVSEND_FIXED_BUF) {  		unsigned idx = READ_ONCE(sqe->buf_index); @@ -898,13 +919,12 @@ int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)  			return -EFAULT;  		idx = array_index_nospec(idx, ctx->nr_user_bufs);  		req->imu = READ_ONCE(ctx->user_bufs[idx]); -		io_req_set_rsrc_node(req, ctx, 0); +		io_req_set_rsrc_node(notif, ctx, 0);  	}  	zc->buf = u64_to_user_ptr(READ_ONCE(sqe->addr));  	zc->len = READ_ONCE(sqe->len);  	zc->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL; -	zc->slot_idx = READ_ONCE(sqe->notification_idx);  	if (zc->msg_flags & MSG_DONTWAIT)  		req->flags |= REQ_F_NOWAIT; @@ -956,7 +976,7 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,  	shinfo->nr_frags = frag;  	from->bvec += bi.bi_idx;  	from->nr_segs -= bi.bi_idx; -	from->count = bi.bi_size; +	from->count -= copied;  	from->iov_offset = bi.bi_bvec_done;  	skb->data_len += copied; @@ -976,33 +996,17 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,  int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)  {  	struct sockaddr_storage __address, *addr = NULL; -	struct io_ring_ctx *ctx = req->ctx;  	struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc); -	struct io_notif_slot *notif_slot; -	struct io_kiocb *notif;  	struct msghdr msg;  	struct iovec iov;  	struct socket *sock; -	unsigned msg_flags; +	unsigned msg_flags, cflags;  	int ret, min_ret = 0; -	if (!(req->flags & REQ_F_POLLED) && -	    (zc->flags & IORING_RECVSEND_POLL_FIRST)) -		return -EAGAIN; - -	if (issue_flags & IO_URING_F_UNLOCKED) -		return -EAGAIN;  	sock = sock_from_file(req->file);  	if (unlikely(!sock))  		return -ENOTSOCK; -	notif_slot = io_get_notif_slot(ctx, zc->slot_idx); -	if (!notif_slot) -		return -EINVAL; -	notif = io_get_notif(ctx, notif_slot); -	if (!notif) -		return -ENOMEM; -  	msg.msg_name = NULL;  	msg.msg_control = NULL;  	msg.msg_controllen = 0; @@ -1023,6 +1027,10 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)  		msg.msg_namelen = zc->addr_len;  	} +	if (!(req->flags & REQ_F_POLLED) && +	    (zc->flags & IORING_RECVSEND_POLL_FIRST)) +		return io_setup_async_addr(req, addr, issue_flags); +  	if (zc->flags & IORING_RECVSEND_FIXED_BUF) {  		ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu,  					(u64)(uintptr_t)zc->buf, zc->len); @@ -1033,7 +1041,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)  					  &msg.msg_iter);  		if (unlikely(ret))  			return ret; -		ret = io_notif_account_mem(notif, zc->len); +		ret = io_notif_account_mem(zc->notif, zc->len);  		if (unlikely(ret))  			return ret;  	} @@ -1045,7 +1053,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)  		min_ret = iov_iter_count(&msg.msg_iter);  	msg.msg_flags = msg_flags; -	msg.msg_ubuf = &io_notif_to_data(notif)->uarg; +	msg.msg_ubuf = &io_notif_to_data(zc->notif)->uarg;  	msg.sg_from_iter = io_sg_from_iter;  	ret = sock_sendmsg(sock, &msg); @@ -1060,18 +1068,22 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)  			req->flags |= REQ_F_PARTIAL_IO;  			return io_setup_async_addr(req, addr, issue_flags);  		} +		if (ret < 0 && !zc->done_io) +			zc->notif->flags |= REQ_F_CQE_SKIP;  		if (ret == -ERESTARTSYS)  			ret = -EINTR;  		req_set_fail(req); -	} else if (zc->flags & IORING_RECVSEND_NOTIF_FLUSH) { -		io_notif_slot_flush_submit(notif_slot, 0);  	}  	if (ret >= 0)  		ret += zc->done_io;  	else if (zc->done_io)  		ret = zc->done_io; -	io_req_set_res(req, ret, 0); + +	io_notif_flush(zc->notif); +	req->flags &= ~REQ_F_NEED_CLEANUP; +	cflags = ret >= 0 ? IORING_CQE_F_MORE : 0; +	io_req_set_res(req, ret, cflags);  	return IOU_OK;  }  | 
