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 | 254 | struct page * *rq_page_end; /* one past the last page */ |
| 255 | 255 | |
| 256 | 256 | struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ |
| 257 | + struct bio_vec rq_bvec[RPCSVC_MAXPAGES]; | |
| 257 | 258 | |
| 258 | 259 | __be32 rq_xid; /* transmission id */ |
| 259 | 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 | 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, | |
| 230 | − unsigned int nr, size_t buflen, unsigned int base) | |
| 250 | +static ssize_t svc_tcp_read_msg(struct svc_rqst *rqstp, size_t buflen, | |
| 251 | + size_t seek) | |
| 231 | 252 | { |
| 232 | 253 | struct svc_sock *svsk = |
| 233 | 254 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
| 255 | + struct bio_vec *bvec = rqstp->rq_bvec; | |
| 234 | 256 | struct msghdr msg = { NULL }; |
| 257 | + unsigned int i; | |
| 235 | 258 | ssize_t len; |
| 259 | + size_t t; | |
| 236 | 260 | |
| 237 | 261 | rqstp->rq_xprt_hlen = 0; |
| 238 | 262 | |
| 239 | 263 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 240 | − iov_iter_kvec(&msg.msg_iter, READ, iov, nr, buflen); | |
| 241 | − if (base != 0) { | |
| 242 | − iov_iter_advance(&msg.msg_iter, base); | |
| 243 | − buflen -= base; | |
| 264 | + | |
| 265 | + for (i = 0, t = 0; t < buflen; i++, t += PAGE_SIZE) { | |
| 266 | + bvec[i].bv_page = rqstp->rq_pages[i]; | |
| 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 | 278 | len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT); |
| 279 | + if (len > 0) | |
| 280 | + svc_flush_bvec(bvec, len, seek); | |
| 281 | + | |
| 246 | 282 | /* If we read a full record, then assume there may be more |
| 247 | 283 | * data to read (stream based sockets only!) |
| 248 | 284 | */ |
| @@ -775,13 +811,14 @@ failed: · 526 unmodified lines | ||
| 775 | 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 | 821 | return 0; |
| 784 | − len = svsk->sk_datalen; | |
| 785 | 822 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 786 | 823 | for (i = 0; i < npages; i++) { |
| 787 | 824 | if (rqstp->rq_pages[i] != NULL) |
| @@ -917,20 +954,6 @@ unlock_eagain: · 129 unmodified lines | ||
| 917 | 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 | 957 | static void svc_tcp_fragment_received(struct svc_sock *svsk) |
| 935 | 958 | { |
| 936 | 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 | 961 | svsk->sk_marker = xdr_zero; |
| 939 | 962 | } |
| 940 | 963 | |
| 941 | −/* | |
| 942 | − * Receive data from a TCP socket. | |
| 964 | +/** | |
| 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 | 982 | static int svc_tcp_recvfrom(struct svc_rqst *rqstp) |
| 945 | 983 | { |
| 946 | 984 | struct svc_sock *svsk = |
| 947 | 985 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); |
| 948 | 986 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
| 949 | − int len; | |
| 950 | − struct kvec *vec; | |
| 951 | − unsigned int want, base; | |
| 987 | + size_t want, base; | |
| 988 | + ssize_t len; | |
| 952 | 989 | __be32 *p; |
| 953 | 990 | __be32 calldir; |
| 954 | − int pnum; | |
| 955 | 991 | |
| 956 | 992 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 957 | 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 | 997 | base = svc_tcp_restore_pages(svsk, rqstp); |
| 962 | 998 | want = len - (svsk->sk_tcplen - sizeof(rpc_fraghdr)); |
| 963 | − | |
| 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); | |
| 999 | + len = svc_tcp_read_msg(rqstp, base + want, base); | |
| 973 | 1000 | if (len >= 0) { |
| 974 | 1001 | trace_svcsock_tcp_recv(&svsk->sk_xprt, len); |
| 975 | 1002 | svsk->sk_tcplen += len; |