aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorRicardo Labiaga <Ricardo.Labiaga@netapp.com>2009-04-01 09:22:53 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 15:43:45 -0400
commit18dca02aeb3c49dfce87c76be643b139d05cf647 (patch)
tree3e261efdba69b967500a36d8f65ac643c8693d76 /net/sunrpc
parent34dc1ad752ad3f55b2a6e6cd8cfcf3504682fec7 (diff)
nfs41: Add ability to read RPC call direction on TCP stream.
NFSv4.1 callbacks can arrive over an existing connection. This patch adds the logic to read the RPC call direction (call or reply). It does this by updating the state machine to look for the call direction invoking xs_tcp_read_calldir(...) after reading the XID. [nfs41: Keep track of RPC call/reply direction with a flag] As per 11/14/08 review of RFC 53/85. Add a new flag to track whether the incoming message is an RPC call or an RPC reply. TCP_RPC_REPLY is set in the 'struct sock_xprt' tcp_flags in xs_tcp_read_calldir() if the message is an RPC reply sent on the forechannel. It is cleared if the message is an RPC request sent on the back channel. 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/xprtsock.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index e18596146013..8975c10591c3 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -270,6 +270,12 @@ 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)
274
275/*
276 * TCP RPC flags
277 */
278#define TCP_RPC_REPLY (1UL << 5)
273 279
274static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) 280static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
275{ 281{
@@ -956,7 +962,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
956 transport->tcp_offset = 0; 962 transport->tcp_offset = 0;
957 963
958 /* Sanity check of the record length */ 964 /* Sanity check of the record length */
959 if (unlikely(transport->tcp_reclen < 4)) { 965 if (unlikely(transport->tcp_reclen < 8)) {
960 dprintk("RPC: invalid TCP record fragment length\n"); 966 dprintk("RPC: invalid TCP record fragment length\n");
961 xprt_force_disconnect(xprt); 967 xprt_force_disconnect(xprt);
962 return; 968 return;
@@ -991,13 +997,48 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
991 if (used != len) 997 if (used != len)
992 return; 998 return;
993 transport->tcp_flags &= ~TCP_RCV_COPY_XID; 999 transport->tcp_flags &= ~TCP_RCV_COPY_XID;
994 transport->tcp_flags |= TCP_RCV_COPY_DATA; 1000 transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
995 transport->tcp_copied = 4; 1001 transport->tcp_copied = 4;
996 dprintk("RPC: reading reply for XID %08x\n", 1002 dprintk("RPC: reading %s XID %08x\n",
1003 (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for"
1004 : "request with",
997 ntohl(transport->tcp_xid)); 1005 ntohl(transport->tcp_xid));
998 xs_tcp_check_fraghdr(transport); 1006 xs_tcp_check_fraghdr(transport);
999} 1007}
1000 1008
1009static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
1010 struct xdr_skb_reader *desc)
1011{
1012 size_t len, used;
1013 u32 offset;
1014 __be32 calldir;
1015
1016 /*
1017 * We want transport->tcp_offset to be 8 at the end of this routine
1018 * (4 bytes for the xid and 4 bytes for the call/reply flag).
1019 * When this function is called for the first time,
1020 * transport->tcp_offset is 4 (after having already read the xid).
1021 */
1022 offset = transport->tcp_offset - sizeof(transport->tcp_xid);
1023 len = sizeof(calldir) - offset;
1024 dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
1025 used = xdr_skb_read_bits(desc, &calldir, len);
1026 transport->tcp_offset += used;
1027 if (used != len)
1028 return;
1029 transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
1030 transport->tcp_flags |= TCP_RCV_COPY_DATA;
1031 transport->tcp_copied += 4;
1032 if (ntohl(calldir) == RPC_REPLY)
1033 transport->tcp_flags |= TCP_RPC_REPLY;
1034 else
1035 transport->tcp_flags &= ~TCP_RPC_REPLY;
1036 dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
1037 (transport->tcp_flags & TCP_RPC_REPLY) ?
1038 "reply for" : "request with", calldir);
1039 xs_tcp_check_fraghdr(transport);
1040}
1041
1001static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) 1042static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
1002{ 1043{
1003 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 1044 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1114,6 +1155,11 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
1114 xs_tcp_read_xid(transport, &desc); 1155 xs_tcp_read_xid(transport, &desc);
1115 continue; 1156 continue;
1116 } 1157 }
1158 /* Read in the call/reply flag */
1159 if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
1160 xs_tcp_read_calldir(transport, &desc);
1161 continue;
1162 }
1117 /* Read in the request data */ 1163 /* Read in the request data */
1118 if (transport->tcp_flags & TCP_RCV_COPY_DATA) { 1164 if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
1119 xs_tcp_read_request(xprt, &desc); 1165 xs_tcp_read_request(xprt, &desc);