diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
| -rw-r--r-- | net/sunrpc/svcsock.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 4de8626e4f54..25096d53667a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -313,7 +313,7 @@ svc_sock_release(struct svc_rqst *rqstp) | |||
| 313 | 313 | ||
| 314 | svc_release_skb(rqstp); | 314 | svc_release_skb(rqstp); |
| 315 | 315 | ||
| 316 | svc_free_allpages(rqstp); | 316 | svc_free_res_pages(rqstp); |
| 317 | rqstp->rq_res.page_len = 0; | 317 | rqstp->rq_res.page_len = 0; |
| 318 | rqstp->rq_res.page_base = 0; | 318 | rqstp->rq_res.page_base = 0; |
| 319 | 319 | ||
| @@ -412,7 +412,8 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | |||
| 412 | /* send head */ | 412 | /* send head */ |
| 413 | if (slen == xdr->head[0].iov_len) | 413 | if (slen == xdr->head[0].iov_len) |
| 414 | flags = 0; | 414 | flags = 0; |
| 415 | len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags); | 415 | len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, |
| 416 | xdr->head[0].iov_len, flags); | ||
| 416 | if (len != xdr->head[0].iov_len) | 417 | if (len != xdr->head[0].iov_len) |
| 417 | goto out; | 418 | goto out; |
| 418 | slen -= xdr->head[0].iov_len; | 419 | slen -= xdr->head[0].iov_len; |
| @@ -437,8 +438,9 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | |||
| 437 | } | 438 | } |
| 438 | /* send tail */ | 439 | /* send tail */ |
| 439 | if (xdr->tail[0].iov_len) { | 440 | if (xdr->tail[0].iov_len) { |
| 440 | result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], | 441 | result = kernel_sendpage(sock, rqstp->rq_respages[0], |
| 441 | ((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1), | 442 | ((unsigned long)xdr->tail[0].iov_base) |
| 443 | & (PAGE_SIZE-1), | ||
| 442 | xdr->tail[0].iov_len, 0); | 444 | xdr->tail[0].iov_len, 0); |
| 443 | 445 | ||
| 444 | if (result > 0) | 446 | if (result > 0) |
| @@ -708,9 +710,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 708 | if (len <= rqstp->rq_arg.head[0].iov_len) { | 710 | if (len <= rqstp->rq_arg.head[0].iov_len) { |
| 709 | rqstp->rq_arg.head[0].iov_len = len; | 711 | rqstp->rq_arg.head[0].iov_len = len; |
| 710 | rqstp->rq_arg.page_len = 0; | 712 | rqstp->rq_arg.page_len = 0; |
| 713 | rqstp->rq_respages = rqstp->rq_pages+1; | ||
| 711 | } else { | 714 | } else { |
| 712 | rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; | 715 | rqstp->rq_arg.page_len = len - rqstp->rq_arg.head[0].iov_len; |
| 713 | rqstp->rq_argused += (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE; | 716 | rqstp->rq_respages = rqstp->rq_pages + 1 + |
| 717 | (rqstp->rq_arg.page_len + PAGE_SIZE - 1)/ PAGE_SIZE; | ||
| 714 | } | 718 | } |
| 715 | 719 | ||
| 716 | if (serv->sv_stats) | 720 | if (serv->sv_stats) |
| @@ -1053,11 +1057,12 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 1053 | vlen = PAGE_SIZE; | 1057 | vlen = PAGE_SIZE; |
| 1054 | pnum = 1; | 1058 | pnum = 1; |
| 1055 | while (vlen < len) { | 1059 | while (vlen < len) { |
| 1056 | vec[pnum].iov_base = page_address(rqstp->rq_argpages[rqstp->rq_argused++]); | 1060 | vec[pnum].iov_base = page_address(rqstp->rq_pages[pnum]); |
| 1057 | vec[pnum].iov_len = PAGE_SIZE; | 1061 | vec[pnum].iov_len = PAGE_SIZE; |
| 1058 | pnum++; | 1062 | pnum++; |
| 1059 | vlen += PAGE_SIZE; | 1063 | vlen += PAGE_SIZE; |
| 1060 | } | 1064 | } |
| 1065 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; | ||
| 1061 | 1066 | ||
| 1062 | /* Now receive data */ | 1067 | /* Now receive data */ |
| 1063 | len = svc_recvfrom(rqstp, vec, pnum, len); | 1068 | len = svc_recvfrom(rqstp, vec, pnum, len); |
| @@ -1209,7 +1214,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
| 1209 | struct svc_sock *svsk =NULL; | 1214 | struct svc_sock *svsk =NULL; |
| 1210 | struct svc_serv *serv = rqstp->rq_server; | 1215 | struct svc_serv *serv = rqstp->rq_server; |
| 1211 | struct svc_pool *pool = rqstp->rq_pool; | 1216 | struct svc_pool *pool = rqstp->rq_pool; |
| 1212 | int len; | 1217 | int len, i; |
| 1213 | int pages; | 1218 | int pages; |
| 1214 | struct xdr_buf *arg; | 1219 | struct xdr_buf *arg; |
| 1215 | DECLARE_WAITQUEUE(wait, current); | 1220 | DECLARE_WAITQUEUE(wait, current); |
| @@ -1226,27 +1231,22 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
| 1226 | "svc_recv: service %p, wait queue active!\n", | 1231 | "svc_recv: service %p, wait queue active!\n", |
| 1227 | rqstp); | 1232 | rqstp); |
| 1228 | 1233 | ||
| 1229 | /* Initialize the buffers */ | ||
| 1230 | /* first reclaim pages that were moved to response list */ | ||
| 1231 | svc_pushback_allpages(rqstp); | ||
| 1232 | 1234 | ||
| 1233 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 1235 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
| 1234 | pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE; | 1236 | pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE; |
| 1235 | while (rqstp->rq_arghi < pages) { | 1237 | for (i=0; i < pages ; i++) |
| 1236 | struct page *p = alloc_page(GFP_KERNEL); | 1238 | while (rqstp->rq_pages[i] == NULL) { |
| 1237 | if (!p) { | 1239 | struct page *p = alloc_page(GFP_KERNEL); |
| 1238 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); | 1240 | if (!p) |
| 1239 | continue; | 1241 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); |
| 1242 | rqstp->rq_pages[i] = p; | ||
| 1240 | } | 1243 | } |
| 1241 | rqstp->rq_argpages[rqstp->rq_arghi++] = p; | ||
| 1242 | } | ||
| 1243 | 1244 | ||
| 1244 | /* Make arg->head point to first page and arg->pages point to rest */ | 1245 | /* Make arg->head point to first page and arg->pages point to rest */ |
| 1245 | arg = &rqstp->rq_arg; | 1246 | arg = &rqstp->rq_arg; |
| 1246 | arg->head[0].iov_base = page_address(rqstp->rq_argpages[0]); | 1247 | arg->head[0].iov_base = page_address(rqstp->rq_pages[0]); |
| 1247 | arg->head[0].iov_len = PAGE_SIZE; | 1248 | arg->head[0].iov_len = PAGE_SIZE; |
| 1248 | rqstp->rq_argused = 1; | 1249 | arg->pages = rqstp->rq_pages + 1; |
| 1249 | arg->pages = rqstp->rq_argpages + 1; | ||
| 1250 | arg->page_base = 0; | 1250 | arg->page_base = 0; |
| 1251 | /* save at least one page for response */ | 1251 | /* save at least one page for response */ |
| 1252 | arg->page_len = (pages-2)*PAGE_SIZE; | 1252 | arg->page_len = (pages-2)*PAGE_SIZE; |
| @@ -1704,6 +1704,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp) | |||
| 1704 | rqstp->rq_prot = dr->prot; | 1704 | rqstp->rq_prot = dr->prot; |
| 1705 | rqstp->rq_addr = dr->addr; | 1705 | rqstp->rq_addr = dr->addr; |
| 1706 | rqstp->rq_daddr = dr->daddr; | 1706 | rqstp->rq_daddr = dr->daddr; |
| 1707 | rqstp->rq_respages = rqstp->rq_pages; | ||
| 1707 | return dr->argslen<<2; | 1708 | return dr->argslen<<2; |
| 1708 | } | 1709 | } |
| 1709 | 1710 | ||
