diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 144 |
1 files changed, 112 insertions, 32 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 40b502b11442..a4fafcbc6ea0 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -387,6 +387,33 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, | |||
387 | return len; | 387 | return len; |
388 | } | 388 | } |
389 | 389 | ||
390 | static int svc_partial_recvfrom(struct svc_rqst *rqstp, | ||
391 | struct kvec *iov, int nr, | ||
392 | int buflen, unsigned int base) | ||
393 | { | ||
394 | size_t save_iovlen; | ||
395 | void __user *save_iovbase; | ||
396 | unsigned int i; | ||
397 | int ret; | ||
398 | |||
399 | if (base == 0) | ||
400 | return svc_recvfrom(rqstp, iov, nr, buflen); | ||
401 | |||
402 | for (i = 0; i < nr; i++) { | ||
403 | if (iov[i].iov_len > base) | ||
404 | break; | ||
405 | base -= iov[i].iov_len; | ||
406 | } | ||
407 | save_iovlen = iov[i].iov_len; | ||
408 | save_iovbase = iov[i].iov_base; | ||
409 | iov[i].iov_len -= base; | ||
410 | iov[i].iov_base += base; | ||
411 | ret = svc_recvfrom(rqstp, &iov[i], nr - i, buflen); | ||
412 | iov[i].iov_len = save_iovlen; | ||
413 | iov[i].iov_base = save_iovbase; | ||
414 | return ret; | ||
415 | } | ||
416 | |||
390 | /* | 417 | /* |
391 | * Set socket snd and rcv buffer lengths | 418 | * Set socket snd and rcv buffer lengths |
392 | */ | 419 | */ |
@@ -884,6 +911,56 @@ failed: | |||
884 | return NULL; | 911 | return NULL; |
885 | } | 912 | } |
886 | 913 | ||
914 | static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) | ||
915 | { | ||
916 | unsigned int i, len, npages; | ||
917 | |||
918 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) | ||
919 | return 0; | ||
920 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); | ||
921 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
922 | for (i = 0; i < npages; i++) { | ||
923 | if (rqstp->rq_pages[i] != NULL) | ||
924 | put_page(rqstp->rq_pages[i]); | ||
925 | BUG_ON(svsk->sk_pages[i] == NULL); | ||
926 | rqstp->rq_pages[i] = svsk->sk_pages[i]; | ||
927 | svsk->sk_pages[i] = NULL; | ||
928 | } | ||
929 | rqstp->rq_arg.head[0].iov_base = page_address(rqstp->rq_pages[0]); | ||
930 | return len; | ||
931 | } | ||
932 | |||
933 | static void svc_tcp_save_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) | ||
934 | { | ||
935 | unsigned int i, len, npages; | ||
936 | |||
937 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) | ||
938 | return; | ||
939 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); | ||
940 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
941 | for (i = 0; i < npages; i++) { | ||
942 | svsk->sk_pages[i] = rqstp->rq_pages[i]; | ||
943 | rqstp->rq_pages[i] = NULL; | ||
944 | } | ||
945 | } | ||
946 | |||
947 | static void svc_tcp_clear_pages(struct svc_sock *svsk) | ||
948 | { | ||
949 | unsigned int i, len, npages; | ||
950 | |||
951 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) | ||
952 | goto out; | ||
953 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); | ||
954 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
955 | for (i = 0; i < npages; i++) { | ||
956 | BUG_ON(svsk->sk_pages[i] == NULL); | ||
957 | put_page(svsk->sk_pages[i]); | ||
958 | svsk->sk_pages[i] = NULL; | ||
959 | } | ||
960 | out: | ||
961 | svsk->sk_tcplen = 0; | ||
962 | } | ||
963 | |||
887 | /* | 964 | /* |
888 | * Receive data. | 965 | * Receive data. |
889 | * If we haven't gotten the record length yet, get the next four bytes. | 966 | * If we haven't gotten the record length yet, get the next four bytes. |
@@ -928,7 +1005,7 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
928 | if (len < want) { | 1005 | if (len < want) { |
929 | dprintk("svc: short recvfrom while reading record " | 1006 | dprintk("svc: short recvfrom while reading record " |
930 | "length (%d of %d)\n", len, want); | 1007 | "length (%d of %d)\n", len, want); |
931 | goto err_again; /* record header not complete */ | 1008 | return -EAGAIN; |
932 | } | 1009 | } |
933 | 1010 | ||
934 | svsk->sk_reclen = ntohl(svsk->sk_reclen); | 1011 | svsk->sk_reclen = ntohl(svsk->sk_reclen); |
@@ -958,26 +1035,14 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
958 | if (svsk->sk_reclen < 8) | 1035 | if (svsk->sk_reclen < 8) |
959 | goto err_delete; /* client is nuts. */ | 1036 | goto err_delete; /* client is nuts. */ |
960 | 1037 | ||
961 | /* Check whether enough data is available */ | ||
962 | len = svc_recv_available(svsk); | ||
963 | if (len < 0) | ||
964 | goto error; | ||
965 | |||
966 | if (len < svsk->sk_reclen) { | ||
967 | dprintk("svc: incomplete TCP record (%d of %d)\n", | ||
968 | len, svsk->sk_reclen); | ||
969 | goto err_again; /* record not complete */ | ||
970 | } | ||
971 | len = svsk->sk_reclen; | 1038 | len = svsk->sk_reclen; |
972 | 1039 | ||
973 | return len; | 1040 | return len; |
974 | error: | 1041 | error: |
975 | if (len == -EAGAIN) | 1042 | dprintk("RPC: TCP recv_record got %d\n", len); |
976 | dprintk("RPC: TCP recv_record got EAGAIN\n"); | ||
977 | return len; | 1043 | return len; |
978 | err_delete: | 1044 | err_delete: |
979 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1045 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
980 | err_again: | ||
981 | return -EAGAIN; | 1046 | return -EAGAIN; |
982 | } | 1047 | } |
983 | 1048 | ||
@@ -1035,6 +1100,7 @@ static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len) | |||
1035 | return i; | 1100 | return i; |
1036 | } | 1101 | } |
1037 | 1102 | ||
1103 | |||
1038 | /* | 1104 | /* |
1039 | * Receive data from a TCP socket. | 1105 | * Receive data from a TCP socket. |
1040 | */ | 1106 | */ |
@@ -1045,6 +1111,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1045 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | 1111 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
1046 | int len; | 1112 | int len; |
1047 | struct kvec *vec; | 1113 | struct kvec *vec; |
1114 | unsigned int want, base; | ||
1048 | __be32 *p; | 1115 | __be32 *p; |
1049 | __be32 calldir; | 1116 | __be32 calldir; |
1050 | int pnum; | 1117 | int pnum; |
@@ -1058,6 +1125,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1058 | if (len < 0) | 1125 | if (len < 0) |
1059 | goto error; | 1126 | goto error; |
1060 | 1127 | ||
1128 | base = svc_tcp_restore_pages(svsk, rqstp); | ||
1129 | want = svsk->sk_reclen - base; | ||
1130 | |||
1061 | vec = rqstp->rq_vec; | 1131 | vec = rqstp->rq_vec; |
1062 | 1132 | ||
1063 | pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], | 1133 | pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], |
@@ -1066,11 +1136,18 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1066 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; | 1136 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; |
1067 | 1137 | ||
1068 | /* Now receive data */ | 1138 | /* Now receive data */ |
1069 | len = svc_recvfrom(rqstp, vec, pnum, svsk->sk_reclen); | 1139 | len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); |
1070 | if (len < 0) | 1140 | if (len >= 0) |
1071 | goto err_again; | 1141 | svsk->sk_tcplen += len; |
1142 | if (len != want) { | ||
1143 | if (len < 0 && len != -EAGAIN) | ||
1144 | goto err_other; | ||
1145 | svc_tcp_save_pages(svsk, rqstp); | ||
1146 | dprintk("svc: incomplete TCP record (%d of %d)\n", | ||
1147 | svsk->sk_tcplen, svsk->sk_reclen); | ||
1148 | goto err_noclose; | ||
1149 | } | ||
1072 | 1150 | ||
1073 | dprintk("svc: TCP complete record (%d bytes)\n", svsk->sk_reclen); | ||
1074 | rqstp->rq_arg.len = svsk->sk_reclen; | 1151 | rqstp->rq_arg.len = svsk->sk_reclen; |
1075 | rqstp->rq_arg.page_base = 0; | 1152 | rqstp->rq_arg.page_base = 0; |
1076 | if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { | 1153 | if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { |
@@ -1087,7 +1164,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1087 | if (calldir) { | 1164 | if (calldir) { |
1088 | len = receive_cb_reply(svsk, rqstp); | 1165 | len = receive_cb_reply(svsk, rqstp); |
1089 | if (len < 0) | 1166 | if (len < 0) |
1090 | goto err_again; | 1167 | goto error; |
1091 | } | 1168 | } |
1092 | 1169 | ||
1093 | /* Reset TCP read info */ | 1170 | /* Reset TCP read info */ |
@@ -1102,20 +1179,20 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1102 | if (serv->sv_stats) | 1179 | if (serv->sv_stats) |
1103 | serv->sv_stats->nettcpcnt++; | 1180 | serv->sv_stats->nettcpcnt++; |
1104 | 1181 | ||
1182 | dprintk("svc: TCP complete record (%d bytes)\n", rqstp->rq_arg.len); | ||
1105 | return rqstp->rq_arg.len; | 1183 | return rqstp->rq_arg.len; |
1106 | 1184 | ||
1107 | err_again: | ||
1108 | if (len == -EAGAIN) { | ||
1109 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); | ||
1110 | return len; | ||
1111 | } | ||
1112 | error: | 1185 | error: |
1113 | if (len != -EAGAIN) { | 1186 | if (len != -EAGAIN) |
1114 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | 1187 | goto err_other; |
1115 | svsk->sk_xprt.xpt_server->sv_name, -len); | 1188 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); |
1116 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | ||
1117 | } | ||
1118 | return -EAGAIN; | 1189 | return -EAGAIN; |
1190 | err_other: | ||
1191 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | ||
1192 | svsk->sk_xprt.xpt_server->sv_name, -len); | ||
1193 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | ||
1194 | err_noclose: | ||
1195 | return -EAGAIN; /* record not complete */ | ||
1119 | } | 1196 | } |
1120 | 1197 | ||
1121 | /* | 1198 | /* |
@@ -1286,6 +1363,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1286 | 1363 | ||
1287 | svsk->sk_reclen = 0; | 1364 | svsk->sk_reclen = 0; |
1288 | svsk->sk_tcplen = 0; | 1365 | svsk->sk_tcplen = 0; |
1366 | memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); | ||
1289 | 1367 | ||
1290 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | 1368 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
1291 | 1369 | ||
@@ -1544,8 +1622,10 @@ static void svc_tcp_sock_detach(struct svc_xprt *xprt) | |||
1544 | 1622 | ||
1545 | svc_sock_detach(xprt); | 1623 | svc_sock_detach(xprt); |
1546 | 1624 | ||
1547 | if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) | 1625 | if (!test_bit(XPT_LISTENER, &xprt->xpt_flags)) { |
1626 | svc_tcp_clear_pages(svsk); | ||
1548 | kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); | 1627 | kernel_sock_shutdown(svsk->sk_sock, SHUT_RDWR); |
1628 | } | ||
1549 | } | 1629 | } |
1550 | 1630 | ||
1551 | /* | 1631 | /* |