This function is not currently "generic" so remove the documenting comment and rename it appropriately. Its internals are converted to use bio_vecs for reading from the transport socket. In existing typical sunrpc uses of bio_vecs, the bio_vec array is allocated dynamically. Here, instead, an array of bio_vecs is added to svc_rqst. The lifetime of this array can be greater than one call to xpo_recvfrom(): - Multiple calls to xpo_recvfrom() might be needed to read an RPC message completely. - At some later point, rq_arg.bvecs will point to this array and it will carry the received message into svc_process(). I also expect that a future optimization will remove either the rq_vec or rq_pages array in favor of rq_bvec, thus conserving the size of struct svc_rqst.
Unified · Split
| @@ -254,6 +254,7 @@ struct svc_rqst { · 253 unmodified lines | |||
| 254 | struct page * *rq_page_end; /* one past the last page */ | 254 | struct page * *rq_page_end; /* one past the last page */ |
| 255 | 255 | ||
| 256 | struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ | 256 | struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ |
| 257 | struct bio_vec rq_bvec[RPCSVC_MAXPAGES]; | ||
| 257 | 258 | ||
| 258 | __be32 rq_xid; /* transmission id */ | 259 | __be32 rq_xid; /* transmission id */ |
| 259 | u32 rq_prog; /* program number */ | 260 | u32 rq_prog; /* program number */ |
| @@ -223,26 +223,62 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) · 222 unmodified lines | |||
| 223 | return len; | 223 | return len; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE | ||
| 227 | static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek) | ||
| 228 | { | ||
| 229 | struct bvec_iter bi = { | ||
| 230 | .bi_size = size, | ||
| 231 | }; | ||
| 232 | struct bio_vec bv; | ||
| 233 | |||
| 234 | bvec_iter_advance(bvec, &bi, seek & PAGE_MASK); | ||
| 235 | for_each_bvec(bv, bvec, bi, bi) | ||
| 236 | flush_dcache_page(bv.bv_page); | ||
| 237 | } | ||
| 238 | #else | ||
| 239 | static inline void svc_flush_bvec(const struct bio_vec *bvec, size_t size, | ||
| 240 | size_t seek) | ||
| 241 | { | ||
| 242 | } | ||
| 243 | #endif | ||
| 244 | |||
| 226 | /* | 245 | /* |
| 227 | * Generic recvfrom routine. | 246 | * Read from @rqstp's transport socket. The incoming message fills whole |
| 247 | * pages in @rqstp's rq_pages array until the last page of the message | ||
| 248 | * has been received into a partial page. | ||
| 228 | */ | 249 | */ |
| 229 | static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, | 250 | static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen, |
| 230 | unsigned int nr, size_t buflen, unsigned int base) | 251 | size_t seek) |
| 231 | { | 252 | { |
| 232 | struct svc_sock *svsk = | 253 | struct svc_sock *svsk = |
| 233 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | 254 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
| 255 | struct bio_vec *bvec = rqstp->rq_bvec; | ||
| 234 | struct msghdr msg = { NULL }; | 256 | struct msghdr msg = { NULL }; |
| 257 | unsigned int i; | ||
| 235 | ssize_t len; | 258 | ssize_t len; |
| 259 | size_t t; | ||
| 236 | 260 | ||
| 237 | rqstp->rq_xprt_hlen = 0; | 261 | rqstp->rq_xprt_hlen = 0; |
| 238 | 262 | ||
| 239 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 263 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 240 | iov_iter_kvec(&msg.msg_iter, READ, iov, nr, buflen); | 264 | |
| 241 | if (base != 0) { | 265 | for (i = 0, t = 0; t < buflen; i++, t += PAGE_SIZE) { |
| 242 | iov_iter_advance(&msg.msg_iter, base); | 266 | bvec[i].bv_page = rqstp->rq_pages[i]; |
| 243 | buflen -= base; | 267 | bvec[i].bv_len = PAGE_SIZE; |
| 268 | bvec[i].bv_offset = 0; | ||
| 269 | } | ||
| 270 | rqstp->rq_respages = &rqstp->rq_pages[i]; | ||
| 271 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 272 | |||
| 273 | iov_iter_bvec(&msg.msg_iter, READ, bvec, i, buflen); | ||
| 274 | if (seek) { | ||
| 275 | iov_iter_advance(&msg.msg_iter, seek); | ||
| 276 | buflen -= seek; | ||
| 244 | } | 277 | } |
| 245 | len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT); | 278 | len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT); |
| 279 | if (len > 0) | ||
| 280 | svc_flush_bvec(bvec, len, seek); | ||
| 281 | |||
| 246 | /* If we read a full record, then assume there may be more | 282 | /* If we read a full record, then assume there may be more |
| 247 | * data to read (stream based sockets only!) | 283 | * data to read (stream based sockets only!) |
| 248 | */ | 284 | */ |
| @@ -775,13 +811,14 @@ failed: · 526 unmodified lines | |||
| 775 | return NULL; | 811 | return NULL; |
| 776 | } | 812 | } |
| 777 | 813 | ||
| 778 | static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) | 814 | static size_t svc_tcp_restore_pages(struct svc_sock *svsk, |
| 815 | struct svc_rqst *rqstp) | ||
| 779 | { | 816 | { |
| 780 | unsigned int i, len, npages; | 817 | size_t len = svsk->sk_datalen; |
| 818 | unsigned int i, npages; | ||
| 781 | 819 | ||
| 782 | if (svsk->sk_datalen == 0) | 820 | if (!len) |
| 783 | return 0; | 821 | return 0; |
| 784 | len = svsk->sk_datalen; | ||
| 785 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 822 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 786 | for (i = 0; i < npages; i++) { | 823 | for (i = 0; i < npages; i++) { |
| 787 | if (rqstp->rq_pages[i] != NULL) | 824 | if (rqstp->rq_pages[i] != NULL) |
| @@ -917,20 +954,6 @@ unlock_eagain: · 129 unmodified lines | |||
| 917 | return -EAGAIN; | 954 | return -EAGAIN; |
| 918 | } | 955 | } |
| 919 | 956 | ||
| 920 | static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len) | ||
| 921 | { | ||
| 922 | int i = 0; | ||
| 923 | int t = 0; | ||
| 924 | |||
| 925 | while (t < len) { | ||
| 926 | vec[i].iov_base = page_address(pages[i]); | ||
| 927 | vec[i].iov_len = PAGE_SIZE; | ||
| 928 | i++; | ||
| 929 | t += PAGE_SIZE; | ||
| 930 | } | ||
| 931 | return i; | ||
| 932 | } | ||
| 933 | |||
| 934 | static void svc_tcp_fragment_received(struct svc_sock *svsk) | 957 | static void svc_tcp_fragment_received(struct svc_sock *svsk) |
| 935 | { | 958 | { |
| 936 | /* If we have more data, signal svc_xprt_enqueue() to try again */ | 959 | /* If we have more data, signal svc_xprt_enqueue() to try again */ |
| @@ -938,20 +961,33 @@ static void svc_tcp_fragment_received(struct svc_sock *svsk) · 1 unmodified line | |||
| 938 | svsk->sk_marker = xdr_zero; | 961 | svsk->sk_marker = xdr_zero; |
| 939 | } | 962 | } |
| 940 | 963 | ||
| 941 | /* | 964 | /** |
| 942 | * Receive data from a TCP socket. | 965 | * svc_tcp_recvfrom - Receive data from a TCP socket |
| 966 | * @rqstp: request structure into which to receive an RPC Call | ||
| 967 | * | ||
| 968 | * Called in a loop when XPT_DATA has been set. | ||
| 969 | * | ||
| 970 | * Read the 4-byte stream record marker, then use the record length | ||
| 971 | * in that marker to set up exactly the resources needed to receive | ||
| 972 | * the next RPC message into @rqstp. | ||
| 973 | * | ||
| 974 | * Returns: | ||
| 975 | * On success, the number of bytes in a received RPC Call, or | ||
| 976 | * %0 if a complete RPC Call message was not ready to return | ||
| 977 | * | ||
| 978 | * The zero return case handles partial receives and callback Replies. | ||
| 979 | * The state of a partial receive is preserved in the svc_sock for | ||
| 980 | * the next call to svc_tcp_recvfrom. | ||
| 943 | */ | 981 | */ |
| 944 | static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | 982 | static int svc_tcp_recvfrom(struct svc_rqst *rqstp) |
| 945 | { | 983 | { |
| 946 | struct svc_sock *svsk = | 984 | struct svc_sock *svsk = |
| 947 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | 985 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
| 948 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | 986 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
| 949 | int len; | 987 | size_t want, base; |
| 950 | struct kvec *vec; | 988 | ssize_t len; |
| 951 | unsigned int want, base; | ||
| 952 | __be32 *p; | 989 | __be32 *p; |
| 953 | __be32 calldir; | 990 | __be32 calldir; |
| 954 | int pnum; | ||
| 955 | 991 | ||
| 956 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 992 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 957 | len = svc_tcp_read_marker(svsk, rqstp); | 993 | len = svc_tcp_read_marker(svsk, rqstp); |
| @@ -960,16 +996,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) · 2 unmodified lines | |||
| 960 | 996 | ||
| 961 | base = svc_tcp_restore_pages(svsk, rqstp); | 997 | base = svc_tcp_restore_pages(svsk, rqstp); |
| 962 | want = len - (svsk->sk_tcplen - sizeof(rpc_fraghdr)); | 998 | want = len - (svsk->sk_tcplen - sizeof(rpc_fraghdr)); |
| 963 | 999 | len = svc_tcp_read_msg(rqstp, base + want, base); | |
| 964 | vec = rqstp->rq_vec; | ||
| 965 | |||
| 966 | pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], base + want); | ||
| 967 | |||
| 968 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; | ||
| 969 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 970 | |||
| 971 | /* Now receive data */ | ||
| 972 | len = svc_recvfrom(rqstp, vec, pnum, base + want, base); | ||
| 973 | if (len >= 0) { | 1000 | if (len >= 0) { |
| 974 | trace_svcsock_tcp_recv(&svsk->sk_xprt, len); | 1001 | trace_svcsock_tcp_recv(&svsk->sk_xprt, len); |
| 975 | svsk->sk_tcplen += len; | 1002 | svsk->sk_tcplen += len; |