[pnfs] [PATCH 01/11] nfs41: Add ability to read RPC call direction on TCP stream.
Ricardo Labiaga
ricardo.labiaga at netapp.com
Fri Jan 18 13:00:54 EST 2008
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.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
---
net/sunrpc/xprtsock.c | 42 +++++++++++++++++++++++++++++++++++++++---
1 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index da60fb5..8a090f8 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -229,7 +229,8 @@ struct sock_xprt {
* State of TCP reply receive
*/
__be32 tcp_fraghdr,
- tcp_xid;
+ tcp_xid,
+ tcp_calldir; /* Is this a call or a reply? */
u32 tcp_offset,
tcp_reclen;
@@ -265,6 +266,7 @@ struct sock_xprt {
#define TCP_RCV_COPY_FRAGHDR (1UL << 1)
#define TCP_RCV_COPY_XID (1UL << 2)
#define TCP_RCV_COPY_DATA (1UL << 3)
+#define TCP_RCV_COPY_CALLDIR (1UL << 4)
static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
{
@@ -881,7 +883,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
transport->tcp_offset = 0;
/* Sanity check of the record length */
- if (unlikely(transport->tcp_reclen < 4)) {
+ if (unlikely(transport->tcp_reclen < 8)) {
dprintk("RPC: invalid TCP record fragment length\n");
xprt_disconnect(xprt);
return;
@@ -916,13 +918,42 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
if (used != len)
return;
transport->tcp_flags &= ~TCP_RCV_COPY_XID;
- transport->tcp_flags |= TCP_RCV_COPY_DATA;
+ transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
transport->tcp_copied = 4;
dprintk("RPC: reading reply for XID %08x\n",
ntohl(transport->tcp_xid));
xs_tcp_check_fraghdr(transport);
}
+static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
+ struct xdr_skb_reader *desc)
+{
+ size_t len, used;
+ u32 offset;
+ char *p;
+
+ /*
+ * We want transport->tcp_offset to be 8 at the end of this routine
+ * (4 bytes for the xid and 4 bytes for the call/reply flag).
+ * When this function is called for the first time,
+ * transport->tcp_offset is 4 (after having already read the xid).
+ */
+ offset = transport->tcp_offset - sizeof(transport->tcp_xid);
+ len = sizeof(transport->tcp_calldir) - offset;
+ dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
+ p = ((char *) &transport->tcp_calldir) + offset;
+ used = xdr_skb_read_bits(desc, p, len);
+ transport->tcp_offset += used;
+ if (used != len)
+ return;
+ transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
+ transport->tcp_flags |= TCP_RCV_COPY_DATA;
+ transport->tcp_copied += 4;
+ dprintk("RPC: reading reply for CALL/REPLY flag %08x\n",
+ ntohl(transport->tcp_calldir));
+ xs_tcp_check_fraghdr(transport);
+}
+
static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
{
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1039,6 +1070,11 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
xs_tcp_read_xid(transport, &desc);
continue;
}
+ /* Read in the call/reply flag */
+ if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
+ xs_tcp_read_calldir(transport, &desc);
+ continue;
+ }
/* Read in the request data */
if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
xs_tcp_read_request(xprt, &desc);
--
1.5.3.3
More information about the pNFS
mailing list