forked from mirrors/linux
		
	udp: Convert udp_sendpage() to use MSG_SPLICE_PAGES
Convert udp_sendpage() to use sendmsg() with MSG_SPLICE_PAGES rather than directly splicing in the pages itself. This allows ->sendpage() to be replaced by something that can handle multiple multipage folios in a single transaction. Signed-off-by: David Howells <dhowells@redhat.com> cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com> cc: David Ahern <dsahern@kernel.org> cc: Jens Axboe <axboe@kernel.dk> cc: Matthew Wilcox <willy@infradead.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									6d8192bd69
								
							
						
					
					
						commit
						7ac7c98785
					
				
					 1 changed files with 6 additions and 45 deletions
				
			
		|  | @ -1332,54 +1332,15 @@ EXPORT_SYMBOL(udp_sendmsg); | ||||||
| int udp_sendpage(struct sock *sk, struct page *page, int offset, | int udp_sendpage(struct sock *sk, struct page *page, int offset, | ||||||
| 		 size_t size, int flags) | 		 size_t size, int flags) | ||||||
| { | { | ||||||
| 	struct inet_sock *inet = inet_sk(sk); | 	struct bio_vec bvec; | ||||||
| 	struct udp_sock *up = udp_sk(sk); | 	struct msghdr msg = { .msg_flags = flags | MSG_SPLICE_PAGES }; | ||||||
| 	int ret; |  | ||||||
| 
 | 
 | ||||||
| 	if (flags & MSG_SENDPAGE_NOTLAST) | 	if (flags & MSG_SENDPAGE_NOTLAST) | ||||||
| 		flags |= MSG_MORE; | 		msg.msg_flags |= MSG_MORE; | ||||||
| 
 | 
 | ||||||
| 	if (!up->pending) { | 	bvec_set_page(&bvec, page, size, offset); | ||||||
| 		struct msghdr msg = {	.msg_flags = flags|MSG_MORE }; | 	iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); | ||||||
| 
 | 	return udp_sendmsg(sk, &msg, size); | ||||||
| 		/* Call udp_sendmsg to specify destination address which
 |  | ||||||
| 		 * sendpage interface can't pass. |  | ||||||
| 		 * This will succeed only when the socket is connected. |  | ||||||
| 		 */ |  | ||||||
| 		ret = udp_sendmsg(sk, &msg, 0); |  | ||||||
| 		if (ret < 0) |  | ||||||
| 			return ret; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	lock_sock(sk); |  | ||||||
| 
 |  | ||||||
| 	if (unlikely(!up->pending)) { |  | ||||||
| 		release_sock(sk); |  | ||||||
| 
 |  | ||||||
| 		net_dbg_ratelimited("cork failed\n"); |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ret = ip_append_page(sk, &inet->cork.fl.u.ip4, |  | ||||||
| 			     page, offset, size, flags); |  | ||||||
| 	if (ret == -EOPNOTSUPP) { |  | ||||||
| 		release_sock(sk); |  | ||||||
| 		return sock_no_sendpage(sk->sk_socket, page, offset, |  | ||||||
| 					size, flags); |  | ||||||
| 	} |  | ||||||
| 	if (ret < 0) { |  | ||||||
| 		udp_flush_pending_frames(sk); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	up->len += size; |  | ||||||
| 	if (!(READ_ONCE(up->corkflag) || (flags&MSG_MORE))) |  | ||||||
| 		ret = udp_push_pending_frames(sk); |  | ||||||
| 	if (!ret) |  | ||||||
| 		ret = size; |  | ||||||
| out: |  | ||||||
| 	release_sock(sk); |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define UDP_SKB_IS_STATELESS 0x80000000 | #define UDP_SKB_IS_STATELESS 0x80000000 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 David Howells
						David Howells