diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
| -rw-r--r-- | net/sunrpc/svcsock.c | 335 |
1 files changed, 244 insertions, 91 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 23128ee191a..ccc5e83cae5 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #include <linux/sunrpc/msg_prot.h> | 49 | #include <linux/sunrpc/msg_prot.h> |
| 50 | #include <linux/sunrpc/svcsock.h> | 50 | #include <linux/sunrpc/svcsock.h> |
| 51 | #include <linux/sunrpc/stats.h> | 51 | #include <linux/sunrpc/stats.h> |
| 52 | #include <linux/sunrpc/xprt.h> | ||
| 52 | 53 | ||
| 53 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 54 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
| 54 | 55 | ||
| @@ -153,49 +154,27 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | |||
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | /* | 156 | /* |
| 156 | * Generic sendto routine | 157 | * send routine intended to be shared by the fore- and back-channel |
| 157 | */ | 158 | */ |
| 158 | static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | 159 | int svc_send_common(struct socket *sock, struct xdr_buf *xdr, |
| 160 | struct page *headpage, unsigned long headoffset, | ||
| 161 | struct page *tailpage, unsigned long tailoffset) | ||
| 159 | { | 162 | { |
| 160 | struct svc_sock *svsk = | ||
| 161 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | ||
| 162 | struct socket *sock = svsk->sk_sock; | ||
| 163 | int slen; | ||
| 164 | union { | ||
| 165 | struct cmsghdr hdr; | ||
| 166 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
| 167 | } buffer; | ||
| 168 | struct cmsghdr *cmh = &buffer.hdr; | ||
| 169 | int len = 0; | ||
| 170 | int result; | 163 | int result; |
| 171 | int size; | 164 | int size; |
| 172 | struct page **ppage = xdr->pages; | 165 | struct page **ppage = xdr->pages; |
| 173 | size_t base = xdr->page_base; | 166 | size_t base = xdr->page_base; |
| 174 | unsigned int pglen = xdr->page_len; | 167 | unsigned int pglen = xdr->page_len; |
| 175 | unsigned int flags = MSG_MORE; | 168 | unsigned int flags = MSG_MORE; |
| 176 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | 169 | int slen; |
| 170 | int len = 0; | ||
| 177 | 171 | ||
| 178 | slen = xdr->len; | 172 | slen = xdr->len; |
| 179 | 173 | ||
| 180 | if (rqstp->rq_prot == IPPROTO_UDP) { | ||
| 181 | struct msghdr msg = { | ||
| 182 | .msg_name = &rqstp->rq_addr, | ||
| 183 | .msg_namelen = rqstp->rq_addrlen, | ||
| 184 | .msg_control = cmh, | ||
| 185 | .msg_controllen = sizeof(buffer), | ||
| 186 | .msg_flags = MSG_MORE, | ||
| 187 | }; | ||
| 188 | |||
| 189 | svc_set_cmsg_data(rqstp, cmh); | ||
| 190 | |||
| 191 | if (sock_sendmsg(sock, &msg, 0) < 0) | ||
| 192 | goto out; | ||
| 193 | } | ||
| 194 | |||
| 195 | /* send head */ | 174 | /* send head */ |
| 196 | if (slen == xdr->head[0].iov_len) | 175 | if (slen == xdr->head[0].iov_len) |
| 197 | flags = 0; | 176 | flags = 0; |
| 198 | len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, | 177 | len = kernel_sendpage(sock, headpage, headoffset, |
| 199 | xdr->head[0].iov_len, flags); | 178 | xdr->head[0].iov_len, flags); |
| 200 | if (len != xdr->head[0].iov_len) | 179 | if (len != xdr->head[0].iov_len) |
| 201 | goto out; | 180 | goto out; |
| @@ -219,16 +198,58 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | |||
| 219 | base = 0; | 198 | base = 0; |
| 220 | ppage++; | 199 | ppage++; |
| 221 | } | 200 | } |
| 201 | |||
| 222 | /* send tail */ | 202 | /* send tail */ |
| 223 | if (xdr->tail[0].iov_len) { | 203 | if (xdr->tail[0].iov_len) { |
| 224 | result = kernel_sendpage(sock, rqstp->rq_respages[0], | 204 | result = kernel_sendpage(sock, tailpage, tailoffset, |
| 225 | ((unsigned long)xdr->tail[0].iov_base) | 205 | xdr->tail[0].iov_len, 0); |
| 226 | & (PAGE_SIZE-1), | ||
| 227 | xdr->tail[0].iov_len, 0); | ||
| 228 | |||
| 229 | if (result > 0) | 206 | if (result > 0) |
| 230 | len += result; | 207 | len += result; |
| 231 | } | 208 | } |
| 209 | |||
| 210 | out: | ||
| 211 | return len; | ||
| 212 | } | ||
| 213 | |||
| 214 | |||
| 215 | /* | ||
| 216 | * Generic sendto routine | ||
| 217 | */ | ||
| 218 | static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | ||
| 219 | { | ||
| 220 | struct svc_sock *svsk = | ||
| 221 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | ||
| 222 | struct socket *sock = svsk->sk_sock; | ||
| 223 | union { | ||
| 224 | struct cmsghdr hdr; | ||
| 225 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
| 226 | } buffer; | ||
| 227 | struct cmsghdr *cmh = &buffer.hdr; | ||
| 228 | int len = 0; | ||
| 229 | unsigned long tailoff; | ||
| 230 | unsigned long headoff; | ||
| 231 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | ||
| 232 | |||
| 233 | if (rqstp->rq_prot == IPPROTO_UDP) { | ||
| 234 | struct msghdr msg = { | ||
| 235 | .msg_name = &rqstp->rq_addr, | ||
| 236 | .msg_namelen = rqstp->rq_addrlen, | ||
| 237 | .msg_control = cmh, | ||
| 238 | .msg_controllen = sizeof(buffer), | ||
| 239 | .msg_flags = MSG_MORE, | ||
| 240 | }; | ||
| 241 | |||
| 242 | svc_set_cmsg_data(rqstp, cmh); | ||
| 243 | |||
| 244 | if (sock_sendmsg(sock, &msg, 0) < 0) | ||
| 245 | goto out; | ||
| 246 | } | ||
| 247 | |||
| 248 | tailoff = ((unsigned long)xdr->tail[0].iov_base) & (PAGE_SIZE-1); | ||
| 249 | headoff = 0; | ||
| 250 | len = svc_send_common(sock, xdr, rqstp->rq_respages[0], headoff, | ||
| 251 | rqstp->rq_respages[0], tailoff); | ||
| 252 | |||
| 232 | out: | 253 | out: |
| 233 | dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n", | 254 | dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n", |
| 234 | svsk, xdr->head[0].iov_base, xdr->head[0].iov_len, | 255 | svsk, xdr->head[0].iov_base, xdr->head[0].iov_len, |
| @@ -432,29 +453,49 @@ static void svc_tcp_write_space(struct sock *sk) | |||
| 432 | } | 453 | } |
| 433 | 454 | ||
| 434 | /* | 455 | /* |
| 456 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo | ||
| 457 | */ | ||
| 458 | static int svc_udp_get_dest_address4(struct svc_rqst *rqstp, | ||
| 459 | struct cmsghdr *cmh) | ||
| 460 | { | ||
| 461 | struct in_pktinfo *pki = CMSG_DATA(cmh); | ||
| 462 | if (cmh->cmsg_type != IP_PKTINFO) | ||
| 463 | return 0; | ||
| 464 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
| 465 | return 1; | ||
| 466 | } | ||
| 467 | |||
| 468 | /* | ||
| 469 | * See net/ipv6/datagram.c : datagram_recv_ctl | ||
| 470 | */ | ||
| 471 | static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, | ||
| 472 | struct cmsghdr *cmh) | ||
| 473 | { | ||
| 474 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | ||
| 475 | if (cmh->cmsg_type != IPV6_PKTINFO) | ||
| 476 | return 0; | ||
| 477 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | ||
| 478 | return 1; | ||
| 479 | } | ||
| 480 | |||
| 481 | /* | ||
| 435 | * Copy the UDP datagram's destination address to the rqstp structure. | 482 | * Copy the UDP datagram's destination address to the rqstp structure. |
| 436 | * The 'destination' address in this case is the address to which the | 483 | * The 'destination' address in this case is the address to which the |
| 437 | * peer sent the datagram, i.e. our local address. For multihomed | 484 | * peer sent the datagram, i.e. our local address. For multihomed |
| 438 | * hosts, this can change from msg to msg. Note that only the IP | 485 | * hosts, this can change from msg to msg. Note that only the IP |
| 439 | * address changes, the port number should remain the same. | 486 | * address changes, the port number should remain the same. |
| 440 | */ | 487 | */ |
| 441 | static void svc_udp_get_dest_address(struct svc_rqst *rqstp, | 488 | static int svc_udp_get_dest_address(struct svc_rqst *rqstp, |
| 442 | struct cmsghdr *cmh) | 489 | struct cmsghdr *cmh) |
| 443 | { | 490 | { |
| 444 | struct svc_sock *svsk = | 491 | switch (cmh->cmsg_level) { |
| 445 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | 492 | case SOL_IP: |
| 446 | switch (svsk->sk_sk->sk_family) { | 493 | return svc_udp_get_dest_address4(rqstp, cmh); |
| 447 | case AF_INET: { | 494 | case SOL_IPV6: |
| 448 | struct in_pktinfo *pki = CMSG_DATA(cmh); | 495 | return svc_udp_get_dest_address6(rqstp, cmh); |
| 449 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
| 450 | break; | ||
| 451 | } | ||
| 452 | case AF_INET6: { | ||
| 453 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | ||
| 454 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | } | 496 | } |
| 497 | |||
| 498 | return 0; | ||
| 458 | } | 499 | } |
| 459 | 500 | ||
| 460 | /* | 501 | /* |
| @@ -531,16 +572,15 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 531 | 572 | ||
| 532 | rqstp->rq_prot = IPPROTO_UDP; | 573 | rqstp->rq_prot = IPPROTO_UDP; |
| 533 | 574 | ||
| 534 | if (cmh->cmsg_level != IPPROTO_IP || | 575 | if (!svc_udp_get_dest_address(rqstp, cmh)) { |
| 535 | cmh->cmsg_type != IP_PKTINFO) { | ||
| 536 | if (net_ratelimit()) | 576 | if (net_ratelimit()) |
| 537 | printk("rpcsvc: received unknown control message:" | 577 | printk(KERN_WARNING |
| 538 | "%d/%d\n", | 578 | "svc: received unknown control message %d/%d; " |
| 539 | cmh->cmsg_level, cmh->cmsg_type); | 579 | "dropping RPC reply datagram\n", |
| 580 | cmh->cmsg_level, cmh->cmsg_type); | ||
| 540 | skb_free_datagram(svsk->sk_sk, skb); | 581 | skb_free_datagram(svsk->sk_sk, skb); |
| 541 | return 0; | 582 | return 0; |
| 542 | } | 583 | } |
| 543 | svc_udp_get_dest_address(rqstp, cmh); | ||
| 544 | 584 | ||
| 545 | if (skb_is_nonlinear(skb)) { | 585 | if (skb_is_nonlinear(skb)) { |
| 546 | /* we have to copy */ | 586 | /* we have to copy */ |
| @@ -651,8 +691,7 @@ static struct svc_xprt_class svc_udp_class = { | |||
| 651 | 691 | ||
| 652 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | 692 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
| 653 | { | 693 | { |
| 654 | int one = 1; | 694 | int err, level, optname, one = 1; |
| 655 | mm_segment_t oldfs; | ||
| 656 | 695 | ||
| 657 | svc_xprt_init(&svc_udp_class, &svsk->sk_xprt, serv); | 696 | svc_xprt_init(&svc_udp_class, &svsk->sk_xprt, serv); |
| 658 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 697 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
| @@ -671,12 +710,22 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
| 671 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 710 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 672 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 711 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
| 673 | 712 | ||
| 674 | oldfs = get_fs(); | ||
| 675 | set_fs(KERNEL_DS); | ||
| 676 | /* make sure we get destination address info */ | 713 | /* make sure we get destination address info */ |
| 677 | svsk->sk_sock->ops->setsockopt(svsk->sk_sock, IPPROTO_IP, IP_PKTINFO, | 714 | switch (svsk->sk_sk->sk_family) { |
| 678 | (char __user *)&one, sizeof(one)); | 715 | case AF_INET: |
| 679 | set_fs(oldfs); | 716 | level = SOL_IP; |
| 717 | optname = IP_PKTINFO; | ||
| 718 | break; | ||
| 719 | case AF_INET6: | ||
| 720 | level = SOL_IPV6; | ||
| 721 | optname = IPV6_RECVPKTINFO; | ||
| 722 | break; | ||
| 723 | default: | ||
| 724 | BUG(); | ||
| 725 | } | ||
| 726 | err = kernel_setsockopt(svsk->sk_sock, level, optname, | ||
| 727 | (char *)&one, sizeof(one)); | ||
| 728 | dprintk("svc: kernel_setsockopt returned %d\n", err); | ||
| 680 | } | 729 | } |
| 681 | 730 | ||
| 682 | /* | 731 | /* |
| @@ -826,21 +875,15 @@ failed: | |||
| 826 | } | 875 | } |
| 827 | 876 | ||
| 828 | /* | 877 | /* |
| 829 | * Receive data from a TCP socket. | 878 | * Receive data. |
| 879 | * If we haven't gotten the record length yet, get the next four bytes. | ||
| 880 | * Otherwise try to gobble up as much as possible up to the complete | ||
| 881 | * record length. | ||
| 830 | */ | 882 | */ |
| 831 | static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | 883 | static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) |
| 832 | { | 884 | { |
| 833 | struct svc_sock *svsk = | ||
| 834 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | ||
| 835 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | 885 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
| 836 | int len; | 886 | int len; |
| 837 | struct kvec *vec; | ||
| 838 | int pnum, vlen; | ||
| 839 | |||
| 840 | dprintk("svc: tcp_recv %p data %d conn %d close %d\n", | ||
| 841 | svsk, test_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags), | ||
| 842 | test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags), | ||
| 843 | test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)); | ||
| 844 | 887 | ||
| 845 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) | 888 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) |
| 846 | /* sndbuf needs to have room for one request | 889 | /* sndbuf needs to have room for one request |
| @@ -861,10 +904,6 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 861 | 904 | ||
| 862 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 905 | clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 863 | 906 | ||
| 864 | /* Receive data. If we haven't got the record length yet, get | ||
| 865 | * the next four bytes. Otherwise try to gobble up as much as | ||
| 866 | * possible up to the complete record length. | ||
| 867 | */ | ||
| 868 | if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { | 907 | if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { |
| 869 | int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; | 908 | int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; |
| 870 | struct kvec iov; | 909 | struct kvec iov; |
| @@ -879,7 +918,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 879 | dprintk("svc: short recvfrom while reading record " | 918 | dprintk("svc: short recvfrom while reading record " |
| 880 | "length (%d of %d)\n", len, want); | 919 | "length (%d of %d)\n", len, want); |
| 881 | svc_xprt_received(&svsk->sk_xprt); | 920 | svc_xprt_received(&svsk->sk_xprt); |
| 882 | return -EAGAIN; /* record header not complete */ | 921 | goto err_again; /* record header not complete */ |
| 883 | } | 922 | } |
| 884 | 923 | ||
| 885 | svsk->sk_reclen = ntohl(svsk->sk_reclen); | 924 | svsk->sk_reclen = ntohl(svsk->sk_reclen); |
| @@ -894,6 +933,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 894 | "per record not supported\n"); | 933 | "per record not supported\n"); |
| 895 | goto err_delete; | 934 | goto err_delete; |
| 896 | } | 935 | } |
| 936 | |||
| 897 | svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; | 937 | svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; |
| 898 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); | 938 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); |
| 899 | if (svsk->sk_reclen > serv->sv_max_mesg) { | 939 | if (svsk->sk_reclen > serv->sv_max_mesg) { |
| @@ -914,17 +954,121 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 914 | dprintk("svc: incomplete TCP record (%d of %d)\n", | 954 | dprintk("svc: incomplete TCP record (%d of %d)\n", |
| 915 | len, svsk->sk_reclen); | 955 | len, svsk->sk_reclen); |
| 916 | svc_xprt_received(&svsk->sk_xprt); | 956 | svc_xprt_received(&svsk->sk_xprt); |
| 917 | return -EAGAIN; /* record not complete */ | 957 | goto err_again; /* record not complete */ |
| 918 | } | 958 | } |
| 919 | len = svsk->sk_reclen; | 959 | len = svsk->sk_reclen; |
| 920 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 960 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 921 | 961 | ||
| 962 | return len; | ||
| 963 | error: | ||
| 964 | if (len == -EAGAIN) { | ||
| 965 | dprintk("RPC: TCP recv_record got EAGAIN\n"); | ||
| 966 | svc_xprt_received(&svsk->sk_xprt); | ||
| 967 | } | ||
| 968 | return len; | ||
| 969 | err_delete: | ||
| 970 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | ||
| 971 | err_again: | ||
| 972 | return -EAGAIN; | ||
| 973 | } | ||
| 974 | |||
| 975 | static int svc_process_calldir(struct svc_sock *svsk, struct svc_rqst *rqstp, | ||
| 976 | struct rpc_rqst **reqpp, struct kvec *vec) | ||
| 977 | { | ||
| 978 | struct rpc_rqst *req = NULL; | ||
| 979 | u32 *p; | ||
| 980 | u32 xid; | ||
| 981 | u32 calldir; | ||
| 982 | int len; | ||
| 983 | |||
| 984 | len = svc_recvfrom(rqstp, vec, 1, 8); | ||
| 985 | if (len < 0) | ||
| 986 | goto error; | ||
| 987 | |||
| 988 | p = (u32 *)rqstp->rq_arg.head[0].iov_base; | ||
| 989 | xid = *p++; | ||
| 990 | calldir = *p; | ||
| 991 | |||
| 992 | if (calldir == 0) { | ||
| 993 | /* REQUEST is the most common case */ | ||
| 994 | vec[0] = rqstp->rq_arg.head[0]; | ||
| 995 | } else { | ||
| 996 | /* REPLY */ | ||
| 997 | if (svsk->sk_bc_xprt) | ||
| 998 | req = xprt_lookup_rqst(svsk->sk_bc_xprt, xid); | ||
| 999 | |||
| 1000 | if (!req) { | ||
| 1001 | printk(KERN_NOTICE | ||
| 1002 | "%s: Got unrecognized reply: " | ||
| 1003 | "calldir 0x%x sk_bc_xprt %p xid %08x\n", | ||
| 1004 | __func__, ntohl(calldir), | ||
| 1005 | svsk->sk_bc_xprt, xid); | ||
| 1006 | vec[0] = rqstp->rq_arg.head[0]; | ||
| 1007 | goto out; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, | ||
| 1011 | sizeof(struct xdr_buf)); | ||
| 1012 | /* copy the xid and call direction */ | ||
| 1013 | memcpy(req->rq_private_buf.head[0].iov_base, | ||
| 1014 | rqstp->rq_arg.head[0].iov_base, 8); | ||
| 1015 | vec[0] = req->rq_private_buf.head[0]; | ||
| 1016 | } | ||
| 1017 | out: | ||
| 1018 | vec[0].iov_base += 8; | ||
| 1019 | vec[0].iov_len -= 8; | ||
| 1020 | len = svsk->sk_reclen - 8; | ||
| 1021 | error: | ||
| 1022 | *reqpp = req; | ||
| 1023 | return len; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | /* | ||
| 1027 | * Receive data from a TCP socket. | ||
| 1028 | */ | ||
| 1029 | static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | ||
| 1030 | { | ||
| 1031 | struct svc_sock *svsk = | ||
| 1032 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | ||
| 1033 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
| 1034 | int len; | ||
| 1035 | struct kvec *vec; | ||
| 1036 | int pnum, vlen; | ||
| 1037 | struct rpc_rqst *req = NULL; | ||
| 1038 | |||
| 1039 | dprintk("svc: tcp_recv %p data %d conn %d close %d\n", | ||
| 1040 | svsk, test_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags), | ||
| 1041 | test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags), | ||
| 1042 | test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags)); | ||
| 1043 | |||
| 1044 | len = svc_tcp_recv_record(svsk, rqstp); | ||
| 1045 | if (len < 0) | ||
| 1046 | goto error; | ||
| 1047 | |||
| 922 | vec = rqstp->rq_vec; | 1048 | vec = rqstp->rq_vec; |
| 923 | vec[0] = rqstp->rq_arg.head[0]; | 1049 | vec[0] = rqstp->rq_arg.head[0]; |
| 924 | vlen = PAGE_SIZE; | 1050 | vlen = PAGE_SIZE; |
| 1051 | |||
| 1052 | /* | ||
| 1053 | * We have enough data for the whole tcp record. Let's try and read the | ||
| 1054 | * first 8 bytes to get the xid and the call direction. We can use this | ||
| 1055 | * to figure out if this is a call or a reply to a callback. If | ||
| 1056 | * sk_reclen is < 8 (xid and calldir), then this is a malformed packet. | ||
| 1057 | * In that case, don't bother with the calldir and just read the data. | ||
| 1058 | * It will be rejected in svc_process. | ||
| 1059 | */ | ||
| 1060 | if (len >= 8) { | ||
| 1061 | len = svc_process_calldir(svsk, rqstp, &req, vec); | ||
| 1062 | if (len < 0) | ||
| 1063 | goto err_again; | ||
| 1064 | vlen -= 8; | ||
| 1065 | } | ||
| 1066 | |||
| 925 | pnum = 1; | 1067 | pnum = 1; |
| 926 | while (vlen < len) { | 1068 | while (vlen < len) { |
| 927 | vec[pnum].iov_base = page_address(rqstp->rq_pages[pnum]); | 1069 | vec[pnum].iov_base = (req) ? |
| 1070 | page_address(req->rq_private_buf.pages[pnum - 1]) : | ||
| 1071 | page_address(rqstp->rq_pages[pnum]); | ||
| 928 | vec[pnum].iov_len = PAGE_SIZE; | 1072 | vec[pnum].iov_len = PAGE_SIZE; |
| 929 | pnum++; | 1073 | pnum++; |
| 930 | vlen += PAGE_SIZE; | 1074 | vlen += PAGE_SIZE; |
| @@ -934,8 +1078,18 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 934 | /* Now receive data */ | 1078 | /* Now receive data */ |
| 935 | len = svc_recvfrom(rqstp, vec, pnum, len); | 1079 | len = svc_recvfrom(rqstp, vec, pnum, len); |
| 936 | if (len < 0) | 1080 | if (len < 0) |
| 937 | goto error; | 1081 | goto err_again; |
| 938 | 1082 | ||
| 1083 | /* | ||
| 1084 | * Account for the 8 bytes we read earlier | ||
| 1085 | */ | ||
| 1086 | len += 8; | ||
| 1087 | |||
| 1088 | if (req) { | ||
| 1089 | xprt_complete_rqst(req->rq_task, len); | ||
| 1090 | len = 0; | ||
| 1091 | goto out; | ||
| 1092 | } | ||
| 939 | dprintk("svc: TCP complete record (%d bytes)\n", len); | 1093 | dprintk("svc: TCP complete record (%d bytes)\n", len); |
| 940 | rqstp->rq_arg.len = len; | 1094 | rqstp->rq_arg.len = len; |
| 941 | rqstp->rq_arg.page_base = 0; | 1095 | rqstp->rq_arg.page_base = 0; |
| @@ -949,6 +1103,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 949 | rqstp->rq_xprt_ctxt = NULL; | 1103 | rqstp->rq_xprt_ctxt = NULL; |
| 950 | rqstp->rq_prot = IPPROTO_TCP; | 1104 | rqstp->rq_prot = IPPROTO_TCP; |
| 951 | 1105 | ||
| 1106 | out: | ||
| 952 | /* Reset TCP read info */ | 1107 | /* Reset TCP read info */ |
| 953 | svsk->sk_reclen = 0; | 1108 | svsk->sk_reclen = 0; |
| 954 | svsk->sk_tcplen = 0; | 1109 | svsk->sk_tcplen = 0; |
| @@ -960,21 +1115,19 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 960 | 1115 | ||
| 961 | return len; | 1116 | return len; |
| 962 | 1117 | ||
| 963 | err_delete: | 1118 | err_again: |
| 964 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | ||
| 965 | return -EAGAIN; | ||
| 966 | |||
| 967 | error: | ||
| 968 | if (len == -EAGAIN) { | 1119 | if (len == -EAGAIN) { |
| 969 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); | 1120 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); |
| 970 | svc_xprt_received(&svsk->sk_xprt); | 1121 | svc_xprt_received(&svsk->sk_xprt); |
| 971 | } else { | 1122 | return len; |
| 1123 | } | ||
| 1124 | error: | ||
| 1125 | if (len != -EAGAIN) { | ||
| 972 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | 1126 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", |
| 973 | svsk->sk_xprt.xpt_server->sv_name, -len); | 1127 | svsk->sk_xprt.xpt_server->sv_name, -len); |
| 974 | goto err_delete; | 1128 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
| 975 | } | 1129 | } |
| 976 | 1130 | return -EAGAIN; | |
| 977 | return len; | ||
| 978 | } | 1131 | } |
| 979 | 1132 | ||
| 980 | /* | 1133 | /* |
