aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r--net/sunrpc/svcsock.c51
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}
498EXPORT_SYMBOL(svc_sock_names); 505EXPORT_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