|
@@ -325,59 +325,34 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
|
|
/*
|
|
/*
|
|
* Generic recvfrom routine.
|
|
* 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 =
|
|
struct svc_sock *svsk =
|
|
container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt);
|
|
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;
|
|
rqstp->rq_xprt_hlen = 0;
|
|
|
|
|
|
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
|
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
|
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, nr, buflen);
|
|
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
|
|
/* If we read a full record, then assume there may be more
|
|
* data to read (stream based sockets only!)
|
|
* data to read (stream based sockets only!)
|
|
*/
|
|
*/
|
|
if (len == buflen)
|
|
if (len == buflen)
|
|
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
|
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);
|
|
svsk, iov[0].iov_base, iov[0].iov_len, len);
|
|
return 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
|
|
* 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;
|
|
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
|
|
iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
|
|
iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
|
|
iov.iov_len = want;
|
|
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;
|
|
goto error;
|
|
svsk->sk_tcplen += len;
|
|
svsk->sk_tcplen += len;
|
|
|
|
|
|
@@ -1088,14 +1064,13 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
|
|
|
|
|
|
vec = rqstp->rq_vec;
|
|
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_respages = &rqstp->rq_pages[pnum];
|
|
rqstp->rq_next_page = rqstp->rq_respages + 1;
|
|
rqstp->rq_next_page = rqstp->rq_respages + 1;
|
|
|
|
|
|
/* Now receive data */
|
|
/* Now receive data */
|
|
- len = svc_partial_recvfrom(rqstp, vec, pnum, want, base);
|
|
|
|
|
|
+ len = svc_recvfrom(rqstp, vec, pnum, base + want, base);
|
|
if (len >= 0) {
|
|
if (len >= 0) {
|
|
svsk->sk_tcplen += len;
|
|
svsk->sk_tcplen += len;
|
|
svsk->sk_datalen += len;
|
|
svsk->sk_datalen += len;
|