Skip to contentSkip to conversation

NFS/RDMA client stall patches

PATCH Peter Leckie 3 participants 5 messages May 19, 2008 – Jun 12, 2008 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

Peter Leckie

author Reviewed-by Greg Banks
#0 lore raw

Don't call __xprt_get_cong() if this is a retransmit. This prevents __xprt_get_cong() from recursively incrementing the congestion avoidance window for retransmitted data.

X-Sgi-Pv: 971446
<http://bugworks/query.cgi/971446>---

net/sunrpc/xprt.c +2 -1
Index: linux-2.6.25.3/net/sunrpc/xprt.c
===================================================================
@@ -224,7 +224,8 @@ int xprt_reserve_xprt_cong(struct rpc_ta
                       return 1;
               goto out_sleep;
       }
-       if (__xprt_get_cong(xprt, task)) {
+     /*If this is a retransmit don't increment cong*/
+       if ((req && req->rq_ntrans) ||__xprt_get_cong(xprt, task)) {
               xprt->snd_task = task;
               if (req) {
                       req->rq_bytes_sent = 0;
#1 lore raw
Quoted 15 lines · Peter Leckie

Don't call __xprt_get_cong() if this is a retransmit. This prevents __xprt_get_cong() from recursively incrementing the congestion avoidance window for retransmitted data.

X-Sgi-Pv: 971446
<http://bugworks/query.cgi/971446>---
Index: linux-2.6.25.3/net/sunrpc/xprt.c
===================================================================

net/sunrpc/xprt.c int xprt_reserve_xprt_cong(struct rpc_ta · line 231

Quoted 9 lines
net/sunrpc/xprt.c +2 -1
@@ -224,7 +224,8 @@ int xprt_reserve_xprt_cong(struct rpc_ta
                        return 1;
                goto out_sleep;
        }
-       if (__xprt_get_cong(xprt, task)) {
+     /*If this is a retransmit don't increment cong*/
+       if ((req && req->rq_ntrans) ||__xprt_get_cong(xprt, task)) {
                xprt->snd_task = task;
                if (req) {
                        req->rq_bytes_sent = 0;

Why would we not want to increment the congestion avoidance window on retransmitted data? On timeout, xprt_adjust_cwnd will call __xprt_put_cong() prior to the retransmission, so I can't see how this is a 'recursive increment'.

Trond

author Reviewed-by Greg Banks
#2 lore raw
Quoted 33 lines · Trond Myklebust
Quoted 16 lines · Peter Leckie

Don't call __xprt_get_cong() if this is a retransmit. This prevents __xprt_get_cong() from recursively incrementing the congestion avoidance window for retransmitted data.

X-Sgi-Pv: 971446
<http://bugworks/query.cgi/971446>---
Index: linux-2.6.25.3/net/sunrpc/xprt.c
===================================================================

net/sunrpc/xprt.c int xprt_reserve_xprt_cong(struct rpc_ta · line 231

Quoted 9 lines
net/sunrpc/xprt.c +2 -1
@@ -224,7 +224,8 @@ int xprt_reserve_xprt_cong(struct rpc_ta
                        return 1;
                goto out_sleep;
        }
-       if (__xprt_get_cong(xprt, task)) {
+     /*If this is a retransmit don't increment cong*/
+       if ((req && req->rq_ntrans) ||__xprt_get_cong(xprt, task)) {
                xprt->snd_task = task;
                if (req) {
                        req->rq_bytes_sent = 0;

Why would we not want to increment the congestion avoidance window on retransmitted data? On timeout, xprt_adjust_cwnd will call __xprt_put_cong() prior to the retransmission, so I can't see how this is a 'recursive increment'.

Quoted 1 line

Trond

That's a good point you raise there I was looking to closely at the tcp equivalent, the correct fix for this issue would be to implement a timer function for NFS/RDMA pretty much identical to xs_udp_timer(), as follows:

Implement xprt_rdma_timer() to be called when an RPC times out. This is needed to decrement the cong after an rpc times out preventing the congestion aviodance from tripping under retransmitts.

---

net/sunrpc/xprtrdma/transport.c +0 -0
Index: linux-2.6.25.3/net/sunrpc/xprtrdma/transport.c
===================================================================
@@ -450,6 +450,18 @@ out1:

}

/*
+ * xprt_rdma_timer - called when a retransmit timeout occurs on a RDMA transport
+ * @task: task that timed out
+ *
+ * Adjust the congestion window after a retransmit timeout has occurred.
+ */
+static void
+xprt_rdma_timer(struct rpc_task *task)
+{
+ xprt_adjust_cwnd(task, -ETIMEDOUT);
+}
+
+/*
* Close a connection, during shutdown or timeout/reconnect
*/
static void
@@ -755,7 +767,8 @@ static struct rpc_xprt_ops xprt_rdma_pro

       .send_request           = xprt_rdma_send_request,
       .close                  = xprt_rdma_close,
       .destroy                = xprt_rdma_destroy,
-       .print_stats            = xprt_rdma_print_stats
+       .print_stats            = xprt_rdma_print_stats,
+       .timer                  = xprt_rdma_timer

};

static struct xprt_class xprt_rdma = {

Thanks,
Pete

#3 lore raw
Quoted 3 lines · Peter Leckie

That's a good point you raise there I was looking to closely at the tcp equivalent, the correct fix for this issue would be to implement a timer function for NFS/RDMA pretty much identical to xs_udp_timer(), as follows:

Hmm, in fact that runs into a different issue - retransmitting over RDMA isn't allowed, since it consumes server credits and therefore will eventually overrun the connection's receive queue. I have a patch in my queue to force a disconnect in fact, which is the appropriate action. I will send them out soon, it's in with some other post-Connectathon work.

I think with your earlier patch to avoid the 5-second pause, the disconnect action will be prompt and accurate. However, I would still be concerned why the RPC was timing out in the first place. Was there an issue in the server?

Tom.

Quoted 46 lines

Implement xprt_rdma_timer() to be called when an RPC times out. This is needed to decrement the cong after an rpc times out preventing the congestion aviodance from tripping under retransmitts.

---

Index: linux-2.6.25.3/net/sunrpc/xprtrdma/transport.c
===================================================================

net/sunrpc/xprtrdma/transport.c +1 -0
@@ -450,6 +450,18 @@ out1:
 }
 
 /*
+ * xprt_rdma_timer - called when a retransmit timeout occurs on a RDMA 

transport
+ * @task: task that timed out
+ *
+ * Adjust the congestion window after a retransmit timeout has occurred.
+ */

net/sunrpc/xprtrdma/transport.c +7 -0
+static void
+xprt_rdma_timer(struct rpc_task *task)
+{
+       xprt_adjust_cwnd(task, -ETIMEDOUT);
+}
+
+/*
 * Close a connection, during shutdown or timeout/reconnect
 */

static void

net/sunrpc/xprtrdma/transport.c +2 -1
@@ -755,7 +767,8 @@ static struct rpc_xprt_ops xprt_rdma_pro
       .send_request           = xprt_rdma_send_request,
       .close                  = xprt_rdma_close,
       .destroy                = xprt_rdma_destroy,
-       .print_stats            = xprt_rdma_print_stats
+       .print_stats            = xprt_rdma_print_stats,
+       .timer                  = xprt_rdma_timer
 };
 
 static struct xprt_class xprt_rdma = {

A message that is not in the archive (sent off-list or not yet received): RTPCLUEXC1-PRDaogxL000001eb-rtwIt2gI0FxT+ZUat5FNkAK/[email protected]

#5 lore raw
Quoted 11 lines · Thomas
Quoted 2 lines · Peter Leckie

That's a good point you raise there I was looking to closely at the tcp equivalent, the correct fix for this issue would be to implement a timer function for NFS/RDMA pretty much identical to xs_udp_timer(), as follows:

Hmm, in fact that runs into a different issue - retransmitting over RDMA isn't allowed, since it consumes server credits and therefore will eventually overrun the connection's receive queue. I have a patch in my queue to force a disconnect in fact, which is the appropriate action. I will send them out soon, it's in with some other post-Connectathon work.

Quoted 4 lines

I think with your earlier patch to avoid the 5-second pause, the disconnect action will be prompt and accurate. However, I would still be concerned why the RPC was timing out in the first place. Was there an issue in the server?

So this is not a typical runtime issue it was just another reason the NFS/RDMA client failed to reconnect after the server disconnects us. Under this circumstance the client is stalled on congestion and has not received the disconnection event. So what both these patches do is allow the client to try and resend another RPC, this causes rpcrdma_conn_upcall() to be called with an event of RDMA_CM_EVENT_CONNECT_ERROR which
then allows the xprt to be disconnected and reconnected. Without this change what happens is the client sits there for ever waiting for the congestion to drop.

This does ask another question why didn't the DREQ from the server cause the xprt on the client to disconnect. Umm I might try and reproduce this error and see what's happening.

Thanks,
Pete