Merge tag 'nfsd-4.20' of git://linux-nfs.org/~bfields/linux
[muen/linux.git] / net / sunrpc / svcsock.c
index db8bb6b..3b525ac 100644 (file)
@@ -325,59 +325,34 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
 /*
  * Generic recvfrom routine.
  */
-static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr,
-                       int buflen)
+static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov,
+                           unsigned int nr, size_t buflen, unsigned int base)
 {
        struct svc_sock *svsk =
                container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
-       struct msghdr msg = {
-               .msg_flags      = MSG_DONTWAIT,
-       };
-       int len;
+       struct msghdr msg = { NULL };
+       ssize_t len;
 
        rqstp->rq_xprt_hlen = 0;
 
        clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, nr, buflen);
-       len = sock_recvmsg(svsk->sk_sock, &msg, msg.msg_flags);
+       if (base != 0) {
+               iov_iter_advance(&msg.msg_iter, base);
+               buflen -= base;
+       }
+       len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
        /* If we read a full record, then assume there may be more
         * data to read (stream based sockets only!)
         */
        if (len == buflen)
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
 
-       dprintk("svc: socket %p recvfrom(%p, %zu) = %d\n",
+       dprintk("svc: socket %p recvfrom(%p, %zu) = %zd\n",
                svsk, iov[0].iov_base, iov[0].iov_len, len);
        return len;
 }
 
-static int svc_partial_recvfrom(struct svc_rqst *rqstp,
-                               struct kvec *iov, int nr,
-                               int buflen, unsigned int base)
-{
-       size_t save_iovlen;
-       void *save_iovbase;
-       unsigned int i;
-       int ret;
-
-       if (base == 0)
-               return svc_recvfrom(rqstp, iov, nr, buflen);
-
-       for (i = 0; i < nr; i++) {
-               if (iov[i].iov_len > base)
-                       break;
-               base -= iov[i].iov_len;
-       }
-       save_iovlen = iov[i].iov_len;
-       save_iovbase = iov[i].iov_base;
-       iov[i].iov_len -= base;
-       iov[i].iov_base += base;
-       ret = svc_recvfrom(rqstp, &iov[i], nr - i, buflen);
-       iov[i].iov_len = save_iovlen;
-       iov[i].iov_base = save_iovbase;
-       return ret;
-}
-
 /*
  * Set socket snd and rcv buffer lengths
  */
@@ -962,7 +937,8 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
                want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
                iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
                iov.iov_len  = want;
-               if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0)
+               len = svc_recvfrom(rqstp, &iov, 1, want, 0);
+               if (len < 0)
                        goto error;
                svsk->sk_tcplen += len;
 
@@ -1088,14 +1064,13 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
 
        vec = rqstp->rq_vec;
 
-       pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0],
-                                               svsk->sk_datalen + want);
+       pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], base + want);
 
        rqstp->rq_respages = &rqstp->rq_pages[pnum];
        rqstp->rq_next_page = rqstp->rq_respages + 1;
 
        /* Now receive data */
-       len = svc_partial_recvfrom(rqstp, vec, pnum, want, base);
+       len = svc_recvfrom(rqstp, vec, pnum, base + want, base);
        if (len >= 0) {
                svsk->sk_tcplen += len;
                svsk->sk_datalen += len;