Skip to content

Commit e7ce710

Browse files
chuckleveramschuma-ntap
authored andcommitted
xprtrdma: Avoid deadlock when credit window is reset
Update the cwnd while processing the server's reply. Otherwise the next task on the xprt_sending queue is still subject to the old credit window. Currently, no task is awoken if the old congestion window is still exceeded, even if the new window is larger, and a deadlock results. This is an issue during a transport reconnect. Servers don't normally shrink the credit window, but the client does reset it to 1 when reconnecting so the server can safely grow it again. As a minor optimization, remove the hack of grabbing the initial cwnd size (which happens to be RPC_CWNDSCALE) and using that value as the congestion scaling factor. The scaling value is invariant, and we are better off without the multiplication operation. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 4f4cf5a commit e7ce710

File tree

3 files changed

+7
-19
lines changed

3 files changed

+7
-19
lines changed

net/sunrpc/xprtrdma/rpc_rdma.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
716716
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
717717
__be32 *iptr;
718718
int rdmalen, status;
719+
unsigned long cwnd;
719720

720721
/* Check status. If bad, signal disconnect and return rep to pool */
721722
if (rep->rr_len == ~0U) {
@@ -845,6 +846,11 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
845846
break;
846847
}
847848

849+
cwnd = xprt->cwnd;
850+
xprt->cwnd = atomic_read(&r_xprt->rx_buf.rb_credits) << RPC_CWNDSHIFT;
851+
if (xprt->cwnd > cwnd)
852+
xprt_release_rqst_cong(rqst->rq_task);
853+
848854
dprintk("RPC: %s: xprt_complete_rqst(0x%p, 0x%p, %d)\n",
849855
__func__, xprt, rqst, status);
850856
xprt_complete_rqst(rqst->rq_task, status);

net/sunrpc/xprtrdma/transport.c

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -448,23 +448,6 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
448448
}
449449
}
450450

451-
static int
452-
xprt_rdma_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
453-
{
454-
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
455-
int credits = atomic_read(&r_xprt->rx_buf.rb_credits);
456-
457-
/* == RPC_CWNDSCALE @ init, but *after* setup */
458-
if (r_xprt->rx_buf.rb_cwndscale == 0UL) {
459-
r_xprt->rx_buf.rb_cwndscale = xprt->cwnd;
460-
dprintk("RPC: %s: cwndscale %lu\n", __func__,
461-
r_xprt->rx_buf.rb_cwndscale);
462-
BUG_ON(r_xprt->rx_buf.rb_cwndscale <= 0);
463-
}
464-
xprt->cwnd = credits * r_xprt->rx_buf.rb_cwndscale;
465-
return xprt_reserve_xprt_cong(xprt, task);
466-
}
467-
468451
/*
469452
* The RDMA allocate/free functions need the task structure as a place
470453
* to hide the struct rpcrdma_req, which is necessary for the actual send/recv
@@ -686,7 +669,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
686669
*/
687670

688671
static struct rpc_xprt_ops xprt_rdma_procs = {
689-
.reserve_xprt = xprt_rdma_reserve_xprt,
672+
.reserve_xprt = xprt_reserve_xprt_cong,
690673
.release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */
691674
.alloc_slot = xprt_alloc_slot,
692675
.release_request = xprt_release_rqst_cong, /* ditto */

net/sunrpc/xprtrdma/xprt_rdma.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ struct rpcrdma_req {
212212
struct rpcrdma_buffer {
213213
spinlock_t rb_lock; /* protects indexes */
214214
atomic_t rb_credits; /* most recent server credits */
215-
unsigned long rb_cwndscale; /* cached framework rpc_cwndscale */
216215
int rb_max_requests;/* client max requests */
217216
struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */
218217
int rb_send_index;

0 commit comments

Comments
 (0)