diff options
author | Ricardo Labiaga <Ricardo.Labiaga@netapp.com> | 2009-04-01 09:22:54 -0400 |
---|---|---|
committer | Benny Halevy <bhalevy@panasas.com> | 2009-06-17 15:43:46 -0400 |
commit | f4a2e418bfd03a1f25f515e8a92ecd584d96cfc1 (patch) | |
tree | 31ea603214b4c68c338af9373b85eedfe0c11275 /net/sunrpc | |
parent | 18dca02aeb3c49dfce87c76be643b139d05cf647 (diff) |
nfs41: Process the RPC call direction
Reading and storing the RPC direction is a three step process.
1. xs_tcp_read_calldir() reads the RPC direction, but it will not store it
in the XDR buffer since the 'struct rpc_rqst' is not yet available.
2. The 'struct rpc_rqst' is obtained during the TCP_RCV_COPY_DATA state.
This state need not necessarily be preceeded by the TCP_RCV_READ_CALLDIR.
For example, we may be reading a continuation packet to a large reply.
Therefore, we can't simply obtain the 'struct rpc_rqst' during the
TCP_RCV_READ_CALLDIR state and assume it's available during TCP_RCV_COPY_DATA.
This patch adds a new TCP_RCV_READ_CALLDIR flag to indicate the need to
read the RPC direction. It then uses TCP_RCV_COPY_CALLDIR to indicate the
RPC direction needs to be saved after the 'struct rpc_rqst' has been allocated.
3. The 'struct rpc_rqst' is obtained by the xs_tcp_read_data() helper
functions. xs_tcp_read_common() then saves the RPC direction in the XDR
buffer if TCP_RCV_COPY_CALLDIR is set. This will happen when we're reading
the data immediately after the direction was read. xs_tcp_read_common()
then clears this flag.
[was nfs41: Skip past the RPC call direction]
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: sunrpc: Add RPC direction back into the XDR buffer]
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
[nfs41: sunrpc: Don't skip past the RPC call direction]
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Diffstat (limited to 'net/sunrpc')
-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 | } |