diff options
| -rw-r--r-- | net/sunrpc/clnt.c | 5 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 31 |
2 files changed, 28 insertions, 8 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d00e8135f866..aca3ab6fc140 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -1390,13 +1390,14 @@ rpc_verify_header(struct rpc_task *task) | |||
| 1390 | } | 1390 | } |
| 1391 | if ((len -= 3) < 0) | 1391 | if ((len -= 3) < 0) |
| 1392 | goto out_overflow; | 1392 | goto out_overflow; |
| 1393 | p += 1; /* skip XID */ | ||
| 1394 | 1393 | ||
| 1394 | p += 1; /* skip XID */ | ||
| 1395 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1395 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
| 1396 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 1396 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
| 1397 | task->tk_pid, __func__, n); | 1397 | task->tk_pid, __func__, n); |
| 1398 | goto out_garbage; | 1398 | goto out_garbage; |
| 1399 | } | 1399 | } |
| 1400 | |||
| 1400 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1401 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
| 1401 | if (--len < 0) | 1402 | if (--len < 0) |
| 1402 | goto out_overflow; | 1403 | goto out_overflow; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 8975c10591c3..a48df1449ece 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -270,12 +270,13 @@ struct sock_xprt { | |||
| 270 | #define TCP_RCV_COPY_FRAGHDR (1UL << 1) | 270 | #define TCP_RCV_COPY_FRAGHDR (1UL << 1) |
| 271 | #define TCP_RCV_COPY_XID (1UL << 2) | 271 | #define TCP_RCV_COPY_XID (1UL << 2) |
| 272 | #define TCP_RCV_COPY_DATA (1UL << 3) | 272 | #define TCP_RCV_COPY_DATA (1UL << 3) |
| 273 | #define TCP_RCV_COPY_CALLDIR (1UL << 4) | 273 | #define TCP_RCV_READ_CALLDIR (1UL << 4) |
| 274 | #define TCP_RCV_COPY_CALLDIR (1UL << 5) | ||
| 274 | 275 | ||
| 275 | /* | 276 | /* |
| 276 | * TCP RPC flags | 277 | * TCP RPC flags |
| 277 | */ | 278 | */ |
| 278 | #define TCP_RPC_REPLY (1UL << 5) | 279 | #define TCP_RPC_REPLY (1UL << 6) |
| 279 | 280 | ||
| 280 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | 281 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
| 281 | { | 282 | { |
| @@ -997,7 +998,7 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r | |||
| 997 | if (used != len) | 998 | if (used != len) |
| 998 | return; | 999 | return; |
| 999 | transport->tcp_flags &= ~TCP_RCV_COPY_XID; | 1000 | transport->tcp_flags &= ~TCP_RCV_COPY_XID; |
| 1000 | transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; | 1001 | transport->tcp_flags |= TCP_RCV_READ_CALLDIR; |
| 1001 | transport->tcp_copied = 4; | 1002 | transport->tcp_copied = 4; |
| 1002 | dprintk("RPC: reading %s XID %08x\n", | 1003 | dprintk("RPC: reading %s XID %08x\n", |
| 1003 | (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for" | 1004 | (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for" |
| @@ -1026,9 +1027,13 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, | |||
| 1026 | transport->tcp_offset += used; | 1027 | transport->tcp_offset += used; |
| 1027 | if (used != len) | 1028 | if (used != len) |
| 1028 | return; | 1029 | return; |
| 1029 | transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR; | 1030 | transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR; |
| 1031 | transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; | ||
| 1030 | transport->tcp_flags |= TCP_RCV_COPY_DATA; | 1032 | transport->tcp_flags |= TCP_RCV_COPY_DATA; |
| 1031 | transport->tcp_copied += 4; | 1033 | /* |
| 1034 | * We don't yet have the XDR buffer, so we will write the calldir | ||
| 1035 | * out after we get the buffer from the 'struct rpc_rqst' | ||
| 1036 | */ | ||
| 1032 | if (ntohl(calldir) == RPC_REPLY) | 1037 | if (ntohl(calldir) == RPC_REPLY) |
| 1033 | transport->tcp_flags |= TCP_RPC_REPLY; | 1038 | transport->tcp_flags |= TCP_RPC_REPLY; |
| 1034 | else | 1039 | else |
| @@ -1059,6 +1064,20 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
| 1059 | } | 1064 | } |
| 1060 | 1065 | ||
| 1061 | rcvbuf = &req->rq_private_buf; | 1066 | rcvbuf = &req->rq_private_buf; |
| 1067 | |||
| 1068 | if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) { | ||
| 1069 | /* | ||
| 1070 | * Save the RPC direction in the XDR buffer | ||
| 1071 | */ | ||
| 1072 | __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ? | ||
| 1073 | htonl(RPC_REPLY) : 0; | ||
| 1074 | |||
| 1075 | memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied, | ||
| 1076 | &calldir, sizeof(calldir)); | ||
| 1077 | transport->tcp_copied += sizeof(calldir); | ||
| 1078 | transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR; | ||
| 1079 | } | ||
| 1080 | |||
| 1062 | len = desc->count; | 1081 | len = desc->count; |
| 1063 | if (len > transport->tcp_reclen - transport->tcp_offset) { | 1082 | if (len > transport->tcp_reclen - transport->tcp_offset) { |
| 1064 | struct xdr_skb_reader my_desc; | 1083 | struct xdr_skb_reader my_desc; |
| @@ -1156,7 +1175,7 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns | |||
| 1156 | continue; | 1175 | continue; |
| 1157 | } | 1176 | } |
| 1158 | /* Read in the call/reply flag */ | 1177 | /* Read in the call/reply flag */ |
| 1159 | if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) { | 1178 | if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) { |
| 1160 | xs_tcp_read_calldir(transport, &desc); | 1179 | xs_tcp_read_calldir(transport, &desc); |
| 1161 | continue; | 1180 | continue; |
| 1162 | } | 1181 | } |
