diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 4 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 21 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 41 |
3 files changed, 29 insertions, 37 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 638c0b576203..558692d7e465 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1191,7 +1191,6 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) | |||
1191 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base | 1191 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base |
1192 | + resbuf->head[0].iov_len; | 1192 | + resbuf->head[0].iov_len; |
1193 | resbuf->tail[0].iov_len = 0; | 1193 | resbuf->tail[0].iov_len = 0; |
1194 | rqstp->rq_restailpage = 0; | ||
1195 | resv = &resbuf->tail[0]; | 1194 | resv = &resbuf->tail[0]; |
1196 | } else { | 1195 | } else { |
1197 | resv = &resbuf->tail[0]; | 1196 | resv = &resbuf->tail[0]; |
@@ -1240,7 +1239,7 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp) | |||
1240 | inpages = resbuf->pages; | 1239 | inpages = resbuf->pages; |
1241 | /* XXX: Would be better to write some xdr helper functions for | 1240 | /* XXX: Would be better to write some xdr helper functions for |
1242 | * nfs{2,3,4}xdr.c that place the data right, instead of copying: */ | 1241 | * nfs{2,3,4}xdr.c that place the data right, instead of copying: */ |
1243 | if (resbuf->tail[0].iov_base && rqstp->rq_restailpage == 0) { | 1242 | if (resbuf->tail[0].iov_base) { |
1244 | BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base | 1243 | BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base |
1245 | + PAGE_SIZE); | 1244 | + PAGE_SIZE); |
1246 | BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base); | 1245 | BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base); |
@@ -1258,7 +1257,6 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp) | |||
1258 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base | 1257 | resbuf->tail[0].iov_base = resbuf->head[0].iov_base |
1259 | + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE; | 1258 | + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE; |
1260 | resbuf->tail[0].iov_len = 0; | 1259 | resbuf->tail[0].iov_len = 0; |
1261 | rqstp->rq_restailpage = 0; | ||
1262 | } | 1260 | } |
1263 | if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages)) | 1261 | if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages)) |
1264 | return -ENOMEM; | 1262 | return -ENOMEM; |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index a99e67b164c1..f4a509a925b5 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -417,18 +417,15 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) | |||
417 | if (size > RPCSVC_MAXPAYLOAD) | 417 | if (size > RPCSVC_MAXPAYLOAD) |
418 | size = RPCSVC_MAXPAYLOAD; | 418 | size = RPCSVC_MAXPAYLOAD; |
419 | pages = 2 + (size+ PAGE_SIZE -1) / PAGE_SIZE; | 419 | pages = 2 + (size+ PAGE_SIZE -1) / PAGE_SIZE; |
420 | rqstp->rq_argused = 0; | ||
421 | rqstp->rq_resused = 0; | ||
422 | arghi = 0; | 420 | arghi = 0; |
423 | BUG_ON(pages > RPCSVC_MAXPAGES); | 421 | BUG_ON(pages > RPCSVC_MAXPAGES); |
424 | while (pages) { | 422 | while (pages) { |
425 | struct page *p = alloc_page(GFP_KERNEL); | 423 | struct page *p = alloc_page(GFP_KERNEL); |
426 | if (!p) | 424 | if (!p) |
427 | break; | 425 | break; |
428 | rqstp->rq_argpages[arghi++] = p; | 426 | rqstp->rq_pages[arghi++] = p; |
429 | pages--; | 427 | pages--; |
430 | } | 428 | } |
431 | rqstp->rq_arghi = arghi; | ||
432 | return ! pages; | 429 | return ! pages; |
433 | } | 430 | } |
434 | 431 | ||
@@ -438,14 +435,10 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) | |||
438 | static void | 435 | static void |
439 | svc_release_buffer(struct svc_rqst *rqstp) | 436 | svc_release_buffer(struct svc_rqst *rqstp) |
440 | { | 437 | { |
441 | while (rqstp->rq_arghi) | 438 | int i; |
442 | put_page(rqstp->rq_argpages[--rqstp->rq_arghi]); | 439 | for (i=0; i<ARRAY_SIZE(rqstp->rq_pages); i++) |
443 | while (rqstp->rq_resused) { | 440 | if (rqstp->rq_pages[i]) |
444 | if (rqstp->rq_respages[--rqstp->rq_resused] == NULL) | 441 | put_page(rqstp->rq_pages[i]); |
445 | continue; | ||
446 | put_page(rqstp->rq_respages[rqstp->rq_resused]); | ||
447 | } | ||
448 | rqstp->rq_argused = 0; | ||
449 | } | 442 | } |
450 | 443 | ||
451 | /* | 444 | /* |
@@ -707,10 +700,10 @@ svc_process(struct svc_rqst *rqstp) | |||
707 | /* setup response xdr_buf. | 700 | /* setup response xdr_buf. |
708 | * Initially it has just one page | 701 | * Initially it has just one page |
709 | */ | 702 | */ |
710 | svc_take_page(rqstp); /* must succeed */ | 703 | rqstp->rq_resused = 1; |
711 | resv->iov_base = page_address(rqstp->rq_respages[0]); | 704 | resv->iov_base = page_address(rqstp->rq_respages[0]); |
712 | resv->iov_len = 0; | 705 | resv->iov_len = 0; |
713 | rqstp->rq_res.pages = rqstp->rq_respages+1; | 706 | rqstp->rq_res.pages = rqstp->rq_respages + 1; |
714 | rqstp->rq_res.len = 0; | 707 | rqstp->rq_res.len = 0; |
715 | rqstp->rq_res.page_base = 0; | 708 | rqstp->rq_res.page_base = 0; |
716 | rqstp->rq_res.page_len = 0; | 709 | rqstp->rq_res.page_len = 0; |
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 | ||