Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Refactor xs_sendpages()

Re-locate xs_sendpages() so that it can be shared with server code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+177 -143
-14
include/linux/sunrpc/xdr.h
··· 188 188 extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); 189 189 extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); 190 190 191 - /* 192 - * Helper structure for copying from an sk_buff. 193 - */ 194 - struct xdr_skb_reader { 195 - struct sk_buff *skb; 196 - unsigned int offset; 197 - size_t count; 198 - __wsum csum; 199 - }; 200 - 201 - typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len); 202 - 203 - extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *); 204 - 205 191 extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32); 206 192 extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *); 207 193
+141
net/sunrpc/socklib.c
··· 14 14 #include <linux/types.h> 15 15 #include <linux/pagemap.h> 16 16 #include <linux/udp.h> 17 + #include <linux/sunrpc/msg_prot.h> 17 18 #include <linux/sunrpc/xdr.h> 18 19 #include <linux/export.h> 19 20 21 + #include "socklib.h" 22 + 23 + /* 24 + * Helper structure for copying from an sk_buff. 25 + */ 26 + struct xdr_skb_reader { 27 + struct sk_buff *skb; 28 + unsigned int offset; 29 + size_t count; 30 + __wsum csum; 31 + }; 32 + 33 + typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, 34 + size_t len); 20 35 21 36 /** 22 37 * xdr_skb_read_bits - copy some data bits from skb to internal buffer ··· 201 186 return 0; 202 187 } 203 188 EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr); 189 + 190 + static inline int xprt_sendmsg(struct socket *sock, struct msghdr *msg, 191 + size_t seek) 192 + { 193 + if (seek) 194 + iov_iter_advance(&msg->msg_iter, seek); 195 + return sock_sendmsg(sock, msg); 196 + } 197 + 198 + static int xprt_send_kvec(struct socket *sock, struct msghdr *msg, 199 + struct kvec *vec, size_t seek) 200 + { 201 + iov_iter_kvec(&msg->msg_iter, WRITE, vec, 1, vec->iov_len); 202 + return xprt_sendmsg(sock, msg, seek); 203 + } 204 + 205 + static int xprt_send_pagedata(struct socket *sock, struct msghdr *msg, 206 + struct xdr_buf *xdr, size_t base) 207 + { 208 + int err; 209 + 210 + err = xdr_alloc_bvec(xdr, GFP_KERNEL); 211 + if (err < 0) 212 + return err; 213 + 214 + iov_iter_bvec(&msg->msg_iter, WRITE, xdr->bvec, xdr_buf_pagecount(xdr), 215 + xdr->page_len + xdr->page_base); 216 + return xprt_sendmsg(sock, msg, base + xdr->page_base); 217 + } 218 + 219 + /* Common case: 220 + * - stream transport 221 + * - sending from byte 0 of the message 222 + * - the message is wholly contained in @xdr's head iovec 223 + */ 224 + static int xprt_send_rm_and_kvec(struct socket *sock, struct msghdr *msg, 225 + rpc_fraghdr marker, struct kvec *vec, 226 + size_t base) 227 + { 228 + struct kvec iov[2] = { 229 + [0] = { 230 + .iov_base = &marker, 231 + .iov_len = sizeof(marker) 232 + }, 233 + [1] = *vec, 234 + }; 235 + size_t len = iov[0].iov_len + iov[1].iov_len; 236 + 237 + iov_iter_kvec(&msg->msg_iter, WRITE, iov, 2, len); 238 + return xprt_sendmsg(sock, msg, base); 239 + } 240 + 241 + /** 242 + * xprt_sock_sendmsg - write an xdr_buf directly to a socket 243 + * @sock: open socket to send on 244 + * @msg: socket message metadata 245 + * @xdr: xdr_buf containing this request 246 + * @base: starting position in the buffer 247 + * @marker: stream record marker field 248 + * @sent_p: return the total number of bytes successfully queued for sending 249 + * 250 + * Return values: 251 + * On success, returns zero and fills in @sent_p. 252 + * %-ENOTSOCK if @sock is not a struct socket. 253 + */ 254 + int xprt_sock_sendmsg(struct socket *sock, struct msghdr *msg, 255 + struct xdr_buf *xdr, unsigned int base, 256 + rpc_fraghdr marker, unsigned int *sent_p) 257 + { 258 + unsigned int rmsize = marker ? sizeof(marker) : 0; 259 + unsigned int remainder = rmsize + xdr->len - base; 260 + unsigned int want; 261 + int err = 0; 262 + 263 + *sent_p = 0; 264 + 265 + if (unlikely(!sock)) 266 + return -ENOTSOCK; 267 + 268 + msg->msg_flags |= MSG_MORE; 269 + want = xdr->head[0].iov_len + rmsize; 270 + if (base < want) { 271 + unsigned int len = want - base; 272 + 273 + remainder -= len; 274 + if (remainder == 0) 275 + msg->msg_flags &= ~MSG_MORE; 276 + if (rmsize) 277 + err = xprt_send_rm_and_kvec(sock, msg, marker, 278 + &xdr->head[0], base); 279 + else 280 + err = xprt_send_kvec(sock, msg, &xdr->head[0], base); 281 + if (remainder == 0 || err != len) 282 + goto out; 283 + *sent_p += err; 284 + base = 0; 285 + } else { 286 + base -= want; 287 + } 288 + 289 + if (base < xdr->page_len) { 290 + unsigned int len = xdr->page_len - base; 291 + 292 + remainder -= len; 293 + if (remainder == 0) 294 + msg->msg_flags &= ~MSG_MORE; 295 + err = xprt_send_pagedata(sock, msg, xdr, base); 296 + if (remainder == 0 || err != len) 297 + goto out; 298 + *sent_p += err; 299 + base = 0; 300 + } else { 301 + base -= xdr->page_len; 302 + } 303 + 304 + if (base >= xdr->tail[0].iov_len) 305 + return 0; 306 + msg->msg_flags &= ~MSG_MORE; 307 + err = xprt_send_kvec(sock, msg, &xdr->tail[0], base); 308 + out: 309 + if (err > 0) { 310 + *sent_p += err; 311 + err = 0; 312 + } 313 + return err; 314 + }
+15
net/sunrpc/socklib.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 4 + * Copyright (C) 2020, Oracle. 5 + */ 6 + 7 + #ifndef _NET_SUNRPC_SOCKLIB_H_ 8 + #define _NET_SUNRPC_SOCKLIB_H_ 9 + 10 + int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb); 11 + int xprt_sock_sendmsg(struct socket *sock, struct msghdr *msg, 12 + struct xdr_buf *xdr, unsigned int base, 13 + rpc_fraghdr marker, unsigned int *sent_p); 14 + 15 + #endif /* _NET_SUNRPC_SOCKLIB_H_ */
+1
net/sunrpc/svcsock.c
··· 55 55 #include <linux/sunrpc/stats.h> 56 56 #include <linux/sunrpc/xprt.h> 57 57 58 + #include "socklib.h" 58 59 #include "sunrpc.h" 59 60 60 61 #define RPCDBG_FACILITY RPCDBG_SVCXPRT
+20 -129
net/sunrpc/xprtsock.c
··· 54 54 55 55 #include <trace/events/sunrpc.h> 56 56 57 + #include "socklib.h" 57 58 #include "sunrpc.h" 58 59 59 60 static void xs_close(struct rpc_xprt *xprt); ··· 750 749 751 750 #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) 752 751 753 - static int xs_sendmsg(struct socket *sock, struct msghdr *msg, size_t seek) 754 - { 755 - if (seek) 756 - iov_iter_advance(&msg->msg_iter, seek); 757 - return sock_sendmsg(sock, msg); 758 - } 759 - 760 - static int xs_send_kvec(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t seek) 761 - { 762 - iov_iter_kvec(&msg->msg_iter, WRITE, vec, 1, vec->iov_len); 763 - return xs_sendmsg(sock, msg, seek); 764 - } 765 - 766 - static int xs_send_pagedata(struct socket *sock, struct msghdr *msg, struct xdr_buf *xdr, size_t base) 767 - { 768 - int err; 769 - 770 - err = xdr_alloc_bvec(xdr, GFP_KERNEL); 771 - if (err < 0) 772 - return err; 773 - 774 - iov_iter_bvec(&msg->msg_iter, WRITE, xdr->bvec, 775 - xdr_buf_pagecount(xdr), 776 - xdr->page_len + xdr->page_base); 777 - return xs_sendmsg(sock, msg, base + xdr->page_base); 778 - } 779 - 780 - #define xs_record_marker_len() sizeof(rpc_fraghdr) 781 - 782 - /* Common case: 783 - * - stream transport 784 - * - sending from byte 0 of the message 785 - * - the message is wholly contained in @xdr's head iovec 786 - */ 787 - static int xs_send_rm_and_kvec(struct socket *sock, struct msghdr *msg, 788 - rpc_fraghdr marker, struct kvec *vec, size_t base) 789 - { 790 - struct kvec iov[2] = { 791 - [0] = { 792 - .iov_base = &marker, 793 - .iov_len = sizeof(marker) 794 - }, 795 - [1] = *vec, 796 - }; 797 - size_t len = iov[0].iov_len + iov[1].iov_len; 798 - 799 - iov_iter_kvec(&msg->msg_iter, WRITE, iov, 2, len); 800 - return xs_sendmsg(sock, msg, base); 801 - } 802 - 803 - /** 804 - * xs_sendpages - write pages directly to a socket 805 - * @sock: socket to send on 806 - * @addr: UDP only -- address of destination 807 - * @addrlen: UDP only -- length of destination address 808 - * @xdr: buffer containing this request 809 - * @base: starting position in the buffer 810 - * @rm: stream record marker field 811 - * @sent_p: return the total number of bytes successfully queued for sending 812 - * 813 - */ 814 - static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, rpc_fraghdr rm, int *sent_p) 815 - { 816 - struct msghdr msg = { 817 - .msg_name = addr, 818 - .msg_namelen = addrlen, 819 - .msg_flags = XS_SENDMSG_FLAGS | MSG_MORE, 820 - }; 821 - unsigned int rmsize = rm ? sizeof(rm) : 0; 822 - unsigned int remainder = rmsize + xdr->len - base; 823 - unsigned int want; 824 - int err = 0; 825 - 826 - if (unlikely(!sock)) 827 - return -ENOTSOCK; 828 - 829 - want = xdr->head[0].iov_len + rmsize; 830 - if (base < want) { 831 - unsigned int len = want - base; 832 - remainder -= len; 833 - if (remainder == 0) 834 - msg.msg_flags &= ~MSG_MORE; 835 - if (rmsize) 836 - err = xs_send_rm_and_kvec(sock, &msg, rm, 837 - &xdr->head[0], base); 838 - else 839 - err = xs_send_kvec(sock, &msg, &xdr->head[0], base); 840 - if (remainder == 0 || err != len) 841 - goto out; 842 - *sent_p += err; 843 - base = 0; 844 - } else 845 - base -= want; 846 - 847 - if (base < xdr->page_len) { 848 - unsigned int len = xdr->page_len - base; 849 - remainder -= len; 850 - if (remainder == 0) 851 - msg.msg_flags &= ~MSG_MORE; 852 - err = xs_send_pagedata(sock, &msg, xdr, base); 853 - if (remainder == 0 || err != len) 854 - goto out; 855 - *sent_p += err; 856 - base = 0; 857 - } else 858 - base -= xdr->page_len; 859 - 860 - if (base >= xdr->tail[0].iov_len) 861 - return 0; 862 - msg.msg_flags &= ~MSG_MORE; 863 - err = xs_send_kvec(sock, &msg, &xdr->tail[0], base); 864 - out: 865 - if (err > 0) { 866 - *sent_p += err; 867 - err = 0; 868 - } 869 - return err; 870 - } 871 - 872 752 /** 873 753 * xs_nospace - handle transmit was incomplete 874 754 * @req: pointer to RPC request ··· 841 959 struct xdr_buf *xdr = &req->rq_snd_buf; 842 960 rpc_fraghdr rm = xs_stream_record_marker(xdr); 843 961 unsigned int msglen = rm ? req->rq_slen + sizeof(rm) : req->rq_slen; 962 + struct msghdr msg = { 963 + .msg_flags = XS_SENDMSG_FLAGS, 964 + }; 965 + unsigned int uninitialized_var(sent); 844 966 int status; 845 - int sent = 0; 846 967 847 968 /* Close the stream if the previous transmission was incomplete */ 848 969 if (xs_send_request_was_aborted(transport, req)) { ··· 857 972 req->rq_svec->iov_base, req->rq_svec->iov_len); 858 973 859 974 req->rq_xtime = ktime_get(); 860 - status = xs_sendpages(transport->sock, NULL, 0, xdr, 861 - transport->xmit.offset, rm, &sent); 975 + status = xprt_sock_sendmsg(transport->sock, &msg, xdr, 976 + transport->xmit.offset, rm, &sent); 862 977 dprintk("RPC: %s(%u) = %d\n", 863 978 __func__, xdr->len - transport->xmit.offset, status); 864 979 ··· 910 1025 struct rpc_xprt *xprt = req->rq_xprt; 911 1026 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 912 1027 struct xdr_buf *xdr = &req->rq_snd_buf; 913 - int sent = 0; 1028 + struct msghdr msg = { 1029 + .msg_name = xs_addr(xprt), 1030 + .msg_namelen = xprt->addrlen, 1031 + .msg_flags = XS_SENDMSG_FLAGS, 1032 + }; 1033 + unsigned int uninitialized_var(sent); 914 1034 int status; 915 1035 916 1036 xs_pktdump("packet data:", ··· 929 1039 return -EBADSLT; 930 1040 931 1041 req->rq_xtime = ktime_get(); 932 - status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, 933 - xdr, 0, 0, &sent); 1042 + status = xprt_sock_sendmsg(transport->sock, &msg, xdr, 0, 0, &sent); 934 1043 935 1044 dprintk("RPC: xs_udp_send_request(%u) = %d\n", 936 1045 xdr->len, status); ··· 995 1106 struct xdr_buf *xdr = &req->rq_snd_buf; 996 1107 rpc_fraghdr rm = xs_stream_record_marker(xdr); 997 1108 unsigned int msglen = rm ? req->rq_slen + sizeof(rm) : req->rq_slen; 1109 + struct msghdr msg = { 1110 + .msg_flags = XS_SENDMSG_FLAGS, 1111 + }; 998 1112 bool vm_wait = false; 1113 + unsigned int uninitialized_var(sent); 999 1114 int status; 1000 - int sent; 1001 1115 1002 1116 /* Close the stream if the previous transmission was incomplete */ 1003 1117 if (xs_send_request_was_aborted(transport, req)) { ··· 1021 1129 * called sendmsg(). */ 1022 1130 req->rq_xtime = ktime_get(); 1023 1131 while (1) { 1024 - sent = 0; 1025 - status = xs_sendpages(transport->sock, NULL, 0, xdr, 1026 - transport->xmit.offset, rm, &sent); 1132 + status = xprt_sock_sendmsg(transport->sock, &msg, xdr, 1133 + transport->xmit.offset, rm, &sent); 1027 1134 1028 1135 dprintk("RPC: xs_tcp_send_request(%u) = %d\n", 1029 1136 xdr->len - transport->xmit.offset, status);