diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index cba85d195222..b39e7e2b648f 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) |
@@ -492,7 +494,12 @@ svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) | |||
492 | } | 494 | } |
493 | spin_unlock(&serv->sv_lock); | 495 | spin_unlock(&serv->sv_lock); |
494 | if (closesk) | 496 | if (closesk) |
497 | /* Should unregister with portmap, but you cannot | ||
498 | * unregister just one protocol... | ||
499 | */ | ||
495 | svc_delete_socket(closesk); | 500 | svc_delete_socket(closesk); |
501 | else if (toclose) | ||
502 | return -ENOENT; | ||
496 | return len; | 503 | return len; |
497 | } | 504 | } |
498 | EXPORT_SYMBOL(svc_sock_names); | 505 | EXPORT_SYMBOL(svc_sock_names); |
@@ -703,9 +710,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
703 | if (len <= rqstp->rq_arg.head[0].iov_len) { | 710 | if (len <= rqstp->rq_arg.head[0].iov_len) { |
704 | rqstp->rq_arg.head[0].iov_len = len; | 711 | rqstp->rq_arg.head[0].iov_len = len; |
705 | rqstp->rq_arg.page_len = 0; | 712 | rqstp->rq_arg.page_len = 0; |
713 | rqstp->rq_respages = rqstp->rq_pages+1; | ||
706 | } else { | 714 | } else { |
707 | 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; |
708 | 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; | ||
709 | } | 718 | } |
710 | 719 | ||
711 | if (serv->sv_stats) | 720 | if (serv->sv_stats) |
@@ -946,7 +955,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
946 | struct svc_sock *svsk = rqstp->rq_sock; | 955 | struct svc_sock *svsk = rqstp->rq_sock; |
947 | struct svc_serv *serv = svsk->sk_server; | 956 | struct svc_serv *serv = svsk->sk_server; |
948 | int len; | 957 | int len; |
949 | struct kvec vec[RPCSVC_MAXPAGES]; | 958 | struct kvec *vec; |
950 | int pnum, vlen; | 959 | int pnum, vlen; |
951 | 960 | ||
952 | dprintk("svc: tcp_recv %p data %d conn %d close %d\n", | 961 | dprintk("svc: tcp_recv %p data %d conn %d close %d\n", |
@@ -1044,15 +1053,17 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1044 | len = svsk->sk_reclen; | 1053 | len = svsk->sk_reclen; |
1045 | set_bit(SK_DATA, &svsk->sk_flags); | 1054 | set_bit(SK_DATA, &svsk->sk_flags); |
1046 | 1055 | ||
1056 | vec = rqstp->rq_vec; | ||
1047 | vec[0] = rqstp->rq_arg.head[0]; | 1057 | vec[0] = rqstp->rq_arg.head[0]; |
1048 | vlen = PAGE_SIZE; | 1058 | vlen = PAGE_SIZE; |
1049 | pnum = 1; | 1059 | pnum = 1; |
1050 | while (vlen < len) { | 1060 | while (vlen < len) { |
1051 | vec[pnum].iov_base = page_address(rqstp->rq_argpages[rqstp->rq_argused++]); | 1061 | vec[pnum].iov_base = page_address(rqstp->rq_pages[pnum]); |
1052 | vec[pnum].iov_len = PAGE_SIZE; | 1062 | vec[pnum].iov_len = PAGE_SIZE; |
1053 | pnum++; | 1063 | pnum++; |
1054 | vlen += PAGE_SIZE; | 1064 | vlen += PAGE_SIZE; |
1055 | } | 1065 | } |
1066 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; | ||
1056 | 1067 | ||
1057 | /* Now receive data */ | 1068 | /* Now receive data */ |
1058 | len = svc_recvfrom(rqstp, vec, pnum, len); | 1069 | len = svc_recvfrom(rqstp, vec, pnum, len); |
@@ -1204,7 +1215,7 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
1204 | struct svc_sock *svsk =NULL; | 1215 | struct svc_sock *svsk =NULL; |
1205 | struct svc_serv *serv = rqstp->rq_server; | 1216 | struct svc_serv *serv = rqstp->rq_server; |
1206 | struct svc_pool *pool = rqstp->rq_pool; | 1217 | struct svc_pool *pool = rqstp->rq_pool; |
1207 | int len; | 1218 | int len, i; |
1208 | int pages; | 1219 | int pages; |
1209 | struct xdr_buf *arg; | 1220 | struct xdr_buf *arg; |
1210 | DECLARE_WAITQUEUE(wait, current); | 1221 | DECLARE_WAITQUEUE(wait, current); |
@@ -1221,27 +1232,22 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
1221 | "svc_recv: service %p, wait queue active!\n", | 1232 | "svc_recv: service %p, wait queue active!\n", |
1222 | rqstp); | 1233 | rqstp); |
1223 | 1234 | ||
1224 | /* Initialize the buffers */ | ||
1225 | /* first reclaim pages that were moved to response list */ | ||
1226 | svc_pushback_allpages(rqstp); | ||
1227 | 1235 | ||
1228 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 1236 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
1229 | pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE; | 1237 | pages = 2 + (serv->sv_bufsz + PAGE_SIZE -1) / PAGE_SIZE; |
1230 | while (rqstp->rq_arghi < pages) { | 1238 | for (i=0; i < pages ; i++) |
1231 | struct page *p = alloc_page(GFP_KERNEL); | 1239 | while (rqstp->rq_pages[i] == NULL) { |
1232 | if (!p) { | 1240 | struct page *p = alloc_page(GFP_KERNEL); |
1233 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); | 1241 | if (!p) |
1234 | continue; | 1242 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); |
1243 | rqstp->rq_pages[i] = p; | ||
1235 | } | 1244 | } |
1236 | rqstp->rq_argpages[rqstp->rq_arghi++] = p; | ||
1237 | } | ||
1238 | 1245 | ||
1239 | /* Make arg->head point to first page and arg->pages point to rest */ | 1246 | /* Make arg->head point to first page and arg->pages point to rest */ |
1240 | arg = &rqstp->rq_arg; | 1247 | arg = &rqstp->rq_arg; |
1241 | arg->head[0].iov_base = page_address(rqstp->rq_argpages[0]); | 1248 | arg->head[0].iov_base = page_address(rqstp->rq_pages[0]); |
1242 | arg->head[0].iov_len = PAGE_SIZE; | 1249 | arg->head[0].iov_len = PAGE_SIZE; |
1243 | rqstp->rq_argused = 1; | 1250 | arg->pages = rqstp->rq_pages + 1; |
1244 | arg->pages = rqstp->rq_argpages + 1; | ||
1245 | arg->page_base = 0; | 1251 | arg->page_base = 0; |
1246 | /* save at least one page for response */ | 1252 | /* save at least one page for response */ |
1247 | arg->page_len = (pages-2)*PAGE_SIZE; | 1253 | arg->page_len = (pages-2)*PAGE_SIZE; |
@@ -1604,6 +1610,8 @@ svc_delete_socket(struct svc_sock *svsk) | |||
1604 | sockfd_put(svsk->sk_sock); | 1610 | sockfd_put(svsk->sk_sock); |
1605 | else | 1611 | else |
1606 | sock_release(svsk->sk_sock); | 1612 | sock_release(svsk->sk_sock); |
1613 | if (svsk->sk_info_authunix != NULL) | ||
1614 | svcauth_unix_info_release(svsk->sk_info_authunix); | ||
1607 | kfree(svsk); | 1615 | kfree(svsk); |
1608 | } else { | 1616 | } else { |
1609 | spin_unlock_bh(&serv->sv_lock); | 1617 | spin_unlock_bh(&serv->sv_lock); |
@@ -1699,6 +1707,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp) | |||
1699 | rqstp->rq_prot = dr->prot; | 1707 | rqstp->rq_prot = dr->prot; |
1700 | rqstp->rq_addr = dr->addr; | 1708 | rqstp->rq_addr = dr->addr; |
1701 | rqstp->rq_daddr = dr->daddr; | 1709 | rqstp->rq_daddr = dr->daddr; |
1710 | rqstp->rq_respages = rqstp->rq_pages; | ||
1702 | return dr->argslen<<2; | 1711 | return dr->argslen<<2; |
1703 | } | 1712 | } |
1704 | 1713 | ||