aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorRicardo Labiaga <Ricardo.Labiaga@netapp.com>2009-04-01 09:22:54 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 15:43:46 -0400
commitf4a2e418bfd03a1f25f515e8a92ecd584d96cfc1 (patch)
tree31ea603214b4c68c338af9373b85eedfe0c11275 /net/sunrpc/xprtsock.c
parent18dca02aeb3c49dfce87c76be643b139d05cf647 (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/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c31
1 files changed, 25 insertions, 6 deletions
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
280static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) 281static 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 }