History

SUNRPC: Refactor svc_recvfrom()

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.

Chuck Lever committed 6 years ago

Commit ca07eda1 parent cca557a2 files · +69 −41Browse files

Unified · Split

2 files
  1. include/linux/sunrpc/svc.h +1 −0
  2. net/sunrpc/svcsock.c +68 −41
include/linux/sunrpc/svc.h+1−0
@@ -254,6 +254,7 @@ struct svc_rqst { · 253 unmodified lines
254254 struct page * *rq_page_end; /* one past the last page */
255255
256256 struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */
257+ struct bio_vec rq_bvec[RPCSVC_MAXPAGES];
257258
258259 __be32 rq_xid; /* transmission id */
259260 u32 rq_prog; /* program number */
net/sunrpc/svcsock.c+68−41
@@ -223,26 +223,62 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) · 222 unmodified lines
223223 return len;
224224 }
225225
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+
226245 /*
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.
228249 */
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)
231252 {
232253 struct svc_sock *svsk =
233254 container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
255+ struct bio_vec *bvec = rqstp->rq_bvec;
234256 struct msghdr msg = { NULL };
257+ unsigned int i;
235258 ssize_t len;
259+ size_t t;
236260
237261 rqstp->rq_xprt_hlen = 0;
238262
239263 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;
244277 }
245278 len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
279+ if (len > 0)
280+ svc_flush_bvec(bvec, len, seek);
281+
246282 /* If we read a full record, then assume there may be more
247283 * data to read (stream based sockets only!)
248284 */
@@ -775,13 +811,14 @@ failed: · 526 unmodified lines
775811 return NULL;
776812 }
777813
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)
779816 {
780− unsigned int i, len, npages;
817+ size_t len = svsk->sk_datalen;
818+ unsigned int i, npages;
781819
782− if (svsk->sk_datalen == 0)
820+ if (!len)
783821 return 0;
784− len = svsk->sk_datalen;
785822 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
786823 for (i = 0; i < npages; i++) {
787824 if (rqstp->rq_pages[i] != NULL)
@@ -917,20 +954,6 @@ unlock_eagain: · 129 unmodified lines
917954 return -EAGAIN;
918955 }
919956
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−
934957 static void svc_tcp_fragment_received(struct svc_sock *svsk)
935958 {
936959 /* 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
938961 svsk->sk_marker = xdr_zero;
939962 }
940963
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.
943981 */
944982 static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
945983 {
946984 struct svc_sock *svsk =
947985 container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
948986 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;
952989 __be32 *p;
953990 __be32 calldir;
954− int pnum;
955991
956992 clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
957993 len = svc_tcp_read_marker(svsk, rqstp);
@@ -960,16 +996,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) · 2 unmodified lines
960996
961997 base = svc_tcp_restore_pages(svsk, rqstp);
962998 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);
9731000 if (len >= 0) {
9741001 trace_svcsock_tcp_recv(&svsk->sk_xprt, len);
9751002 svsk->sk_tcplen += len;