Skip to content

Commit

Permalink
SUNRPC/xprtrdma: Fix reconnection locking
Browse files Browse the repository at this point in the history
The xprtrdma client code currently relies on the task that initiated the
connect to hold the XPRT_LOCK for the duration of the connection
attempt. If the task is woken early, due to some other event, then that
lock could get released early.
Avoid races by using the same mechanism that the socket code uses of
transferring lock ownership to the RDMA connect worker itself. That
frees us to call rpcrdma_xprt_disconnect() directly since we're now
guaranteed exclusion w.r.t. other callers.

Fixes: 4cf44be ("xprtrdma: Fix recursion into rpcrdma_xprt_disconnect()")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
  • Loading branch information
Trond Myklebust authored and amschuma-ntap committed Aug 9, 2021
1 parent e26d997 commit f99fa50
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 6 deletions.
2 changes: 2 additions & 0 deletions net/sunrpc/xprt.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ bool xprt_lock_connect(struct rpc_xprt *xprt,
spin_unlock(&xprt->transport_lock);
return ret;
}
EXPORT_SYMBOL_GPL(xprt_lock_connect);

void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
{
Expand All @@ -893,6 +894,7 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
spin_unlock(&xprt->transport_lock);
wake_up_bit(&xprt->state, XPRT_LOCKED);
}
EXPORT_SYMBOL_GPL(xprt_unlock_connect);

/**
* xprt_connect - schedule a transport connect operation
Expand Down
11 changes: 5 additions & 6 deletions net/sunrpc/xprtrdma/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,9 @@ xprt_rdma_connect_worker(struct work_struct *work)
xprt->stat.connect_start;
xprt_set_connected(xprt);
rc = -EAGAIN;
} else {
/* Force a call to xprt_rdma_close to clean up */
spin_lock(&xprt->transport_lock);
set_bit(XPRT_CLOSE_WAIT, &xprt->state);
spin_unlock(&xprt->transport_lock);
}
} else
rpcrdma_xprt_disconnect(r_xprt);
xprt_unlock_connect(xprt, r_xprt);
xprt_wake_pending_tasks(xprt, rc);
}

Expand Down Expand Up @@ -489,6 +486,8 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
struct rpcrdma_ep *ep = r_xprt->rx_ep;
unsigned long delay;

WARN_ON_ONCE(!xprt_lock_connect(xprt, task, r_xprt));

delay = 0;
if (ep && ep->re_connect_status != 0) {
delay = xprt_reconnect_delay(xprt);
Expand Down

0 comments on commit f99fa50

Please sign in to comment.