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.c98
1 files changed, 50 insertions, 48 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index cc3020d16789..0a148c9d2a5c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -605,6 +605,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
605 rqstp->rq_respages = rqstp->rq_pages + 1 + 605 rqstp->rq_respages = rqstp->rq_pages + 1 +
606 DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE); 606 DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE);
607 } 607 }
608 rqstp->rq_next_page = rqstp->rq_respages+1;
608 609
609 if (serv->sv_stats) 610 if (serv->sv_stats)
610 serv->sv_stats->netudpcnt++; 611 serv->sv_stats->netudpcnt++;
@@ -878,9 +879,9 @@ static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst
878{ 879{
879 unsigned int i, len, npages; 880 unsigned int i, len, npages;
880 881
881 if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) 882 if (svsk->sk_datalen == 0)
882 return 0; 883 return 0;
883 len = svsk->sk_tcplen - sizeof(rpc_fraghdr); 884 len = svsk->sk_datalen;
884 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; 885 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
885 for (i = 0; i < npages; i++) { 886 for (i = 0; i < npages; i++) {
886 if (rqstp->rq_pages[i] != NULL) 887 if (rqstp->rq_pages[i] != NULL)
@@ -897,9 +898,9 @@ static void svc_tcp_save_pages(struct svc_sock *svsk, struct svc_rqst *rqstp)
897{ 898{
898 unsigned int i, len, npages; 899 unsigned int i, len, npages;
899 900
900 if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) 901 if (svsk->sk_datalen == 0)
901 return; 902 return;
902 len = svsk->sk_tcplen - sizeof(rpc_fraghdr); 903 len = svsk->sk_datalen;
903 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; 904 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
904 for (i = 0; i < npages; i++) { 905 for (i = 0; i < npages; i++) {
905 svsk->sk_pages[i] = rqstp->rq_pages[i]; 906 svsk->sk_pages[i] = rqstp->rq_pages[i];
@@ -911,9 +912,9 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
911{ 912{
912 unsigned int i, len, npages; 913 unsigned int i, len, npages;
913 914
914 if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) 915 if (svsk->sk_datalen == 0)
915 goto out; 916 goto out;
916 len = svsk->sk_tcplen - sizeof(rpc_fraghdr); 917 len = svsk->sk_datalen;
917 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; 918 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
918 for (i = 0; i < npages; i++) { 919 for (i = 0; i < npages; i++) {
919 BUG_ON(svsk->sk_pages[i] == NULL); 920 BUG_ON(svsk->sk_pages[i] == NULL);
@@ -922,13 +923,12 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
922 } 923 }
923out: 924out:
924 svsk->sk_tcplen = 0; 925 svsk->sk_tcplen = 0;
926 svsk->sk_datalen = 0;
925} 927}
926 928
927/* 929/*
928 * Receive data. 930 * Receive fragment record header.
929 * If we haven't gotten the record length yet, get the next four bytes. 931 * If we haven't gotten the record length yet, get the next four bytes.
930 * Otherwise try to gobble up as much as possible up to the complete
931 * record length.
932 */ 932 */
933static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) 933static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
934{ 934{
@@ -954,32 +954,16 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
954 return -EAGAIN; 954 return -EAGAIN;
955 } 955 }
956 956
957 svsk->sk_reclen = ntohl(svsk->sk_reclen); 957 dprintk("svc: TCP record, %d bytes\n", svc_sock_reclen(svsk));
958 if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) { 958 if (svc_sock_reclen(svsk) + svsk->sk_datalen >
959 /* FIXME: technically, a record can be fragmented, 959 serv->sv_max_mesg) {
960 * and non-terminal fragments will not have the top 960 net_notice_ratelimited("RPC: fragment too large: %d\n",
961 * bit set in the fragment length header. 961 svc_sock_reclen(svsk));
962 * But apparently no known nfs clients send fragmented
963 * records. */
964 net_notice_ratelimited("RPC: multiple fragments per record not supported\n");
965 goto err_delete;
966 }
967
968 svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
969 dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
970 if (svsk->sk_reclen > serv->sv_max_mesg) {
971 net_notice_ratelimited("RPC: fragment too large: 0x%08lx\n",
972 (unsigned long)svsk->sk_reclen);
973 goto err_delete; 962 goto err_delete;
974 } 963 }
975 } 964 }
976 965
977 if (svsk->sk_reclen < 8) 966 return svc_sock_reclen(svsk);
978 goto err_delete; /* client is nuts. */
979
980 len = svsk->sk_reclen;
981
982 return len;
983error: 967error:
984 dprintk("RPC: TCP recv_record got %d\n", len); 968 dprintk("RPC: TCP recv_record got %d\n", len);
985 return len; 969 return len;
@@ -1023,7 +1007,7 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
1023 if (dst->iov_len < src->iov_len) 1007 if (dst->iov_len < src->iov_len)
1024 return -EAGAIN; /* whatever; just giving up. */ 1008 return -EAGAIN; /* whatever; just giving up. */
1025 memcpy(dst->iov_base, src->iov_base, src->iov_len); 1009 memcpy(dst->iov_base, src->iov_base, src->iov_len);
1026 xprt_complete_rqst(req->rq_task, svsk->sk_reclen); 1010 xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
1027 rqstp->rq_arg.len = 0; 1011 rqstp->rq_arg.len = 0;
1028 return 0; 1012 return 0;
1029} 1013}
@@ -1042,6 +1026,17 @@ static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
1042 return i; 1026 return i;
1043} 1027}
1044 1028
1029static void svc_tcp_fragment_received(struct svc_sock *svsk)
1030{
1031 /* If we have more data, signal svc_xprt_enqueue() to try again */
1032 if (svc_recv_available(svsk) > sizeof(rpc_fraghdr))
1033 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
1034 dprintk("svc: TCP %s record (%d bytes)\n",
1035 svc_sock_final_rec(svsk) ? "final" : "nonfinal",
1036 svc_sock_reclen(svsk));
1037 svsk->sk_tcplen = 0;
1038 svsk->sk_reclen = 0;
1039}
1045 1040
1046/* 1041/*
1047 * Receive data from a TCP socket. 1042 * Receive data from a TCP socket.
@@ -1068,29 +1063,39 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1068 goto error; 1063 goto error;
1069 1064
1070 base = svc_tcp_restore_pages(svsk, rqstp); 1065 base = svc_tcp_restore_pages(svsk, rqstp);
1071 want = svsk->sk_reclen - base; 1066 want = svc_sock_reclen(svsk) - (svsk->sk_tcplen - sizeof(rpc_fraghdr));
1072 1067
1073 vec = rqstp->rq_vec; 1068 vec = rqstp->rq_vec;
1074 1069
1075 pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], 1070 pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0],
1076 svsk->sk_reclen); 1071 svsk->sk_datalen + want);
1077 1072
1078 rqstp->rq_respages = &rqstp->rq_pages[pnum]; 1073 rqstp->rq_respages = &rqstp->rq_pages[pnum];
1074 rqstp->rq_next_page = rqstp->rq_respages + 1;
1079 1075
1080 /* Now receive data */ 1076 /* Now receive data */
1081 len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); 1077 len = svc_partial_recvfrom(rqstp, vec, pnum, want, base);
1082 if (len >= 0) 1078 if (len >= 0) {
1083 svsk->sk_tcplen += len; 1079 svsk->sk_tcplen += len;
1084 if (len != want) { 1080 svsk->sk_datalen += len;
1081 }
1082 if (len != want || !svc_sock_final_rec(svsk)) {
1085 svc_tcp_save_pages(svsk, rqstp); 1083 svc_tcp_save_pages(svsk, rqstp);
1086 if (len < 0 && len != -EAGAIN) 1084 if (len < 0 && len != -EAGAIN)
1087 goto err_other; 1085 goto err_delete;
1088 dprintk("svc: incomplete TCP record (%d of %d)\n", 1086 if (len == want)
1089 svsk->sk_tcplen, svsk->sk_reclen); 1087 svc_tcp_fragment_received(svsk);
1088 else
1089 dprintk("svc: incomplete TCP record (%d of %d)\n",
1090 (int)(svsk->sk_tcplen - sizeof(rpc_fraghdr)),
1091 svc_sock_reclen(svsk));
1090 goto err_noclose; 1092 goto err_noclose;
1091 } 1093 }
1092 1094
1093 rqstp->rq_arg.len = svsk->sk_reclen; 1095 if (svc_sock_reclen(svsk) < 8)
1096 goto err_delete; /* client is nuts. */
1097
1098 rqstp->rq_arg.len = svsk->sk_datalen;
1094 rqstp->rq_arg.page_base = 0; 1099 rqstp->rq_arg.page_base = 0;
1095 if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { 1100 if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
1096 rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; 1101 rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
@@ -1107,11 +1112,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1107 len = receive_cb_reply(svsk, rqstp); 1112 len = receive_cb_reply(svsk, rqstp);
1108 1113
1109 /* Reset TCP read info */ 1114 /* Reset TCP read info */
1110 svsk->sk_reclen = 0; 1115 svsk->sk_datalen = 0;
1111 svsk->sk_tcplen = 0; 1116 svc_tcp_fragment_received(svsk);
1112 /* If we have more data, signal svc_xprt_enqueue() to try again */
1113 if (svc_recv_available(svsk) > sizeof(rpc_fraghdr))
1114 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
1115 1117
1116 if (len < 0) 1118 if (len < 0)
1117 goto error; 1119 goto error;
@@ -1120,15 +1122,14 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1120 if (serv->sv_stats) 1122 if (serv->sv_stats)
1121 serv->sv_stats->nettcpcnt++; 1123 serv->sv_stats->nettcpcnt++;
1122 1124
1123 dprintk("svc: TCP complete record (%d bytes)\n", rqstp->rq_arg.len);
1124 return rqstp->rq_arg.len; 1125 return rqstp->rq_arg.len;
1125 1126
1126error: 1127error:
1127 if (len != -EAGAIN) 1128 if (len != -EAGAIN)
1128 goto err_other; 1129 goto err_delete;
1129 dprintk("RPC: TCP recvfrom got EAGAIN\n"); 1130 dprintk("RPC: TCP recvfrom got EAGAIN\n");
1130 return 0; 1131 return 0;
1131err_other: 1132err_delete:
1132 printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", 1133 printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
1133 svsk->sk_xprt.xpt_server->sv_name, -len); 1134 svsk->sk_xprt.xpt_server->sv_name, -len);
1134 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 1135 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
@@ -1305,6 +1306,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
1305 1306
1306 svsk->sk_reclen = 0; 1307 svsk->sk_reclen = 0;
1307 svsk->sk_tcplen = 0; 1308 svsk->sk_tcplen = 0;
1309 svsk->sk_datalen = 0;
1308 memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); 1310 memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages));
1309 1311
1310 tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; 1312 tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;