Commit 81fe0c57 authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker

xprtrdma: Invoke rpcrdma_ia_open in the connect worker

Move rdma_cm_id creation into rpcrdma_ep_create() so that it is now
responsible for allocating all per-connection hardware resources.

With this clean-up, all three arms of the switch statement in
rpcrdma_ep_connect are exactly the same now, thus the switch can be
removed.

Because device removal behaves a little differently than
disconnection, there is a little more work to be done before
rpcrdma_ep_destroy() can release the connection's rdma_cm_id. So
it is not quite symmetrical with rpcrdma_ep_create() yet.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 9ba373ee
...@@ -415,7 +415,6 @@ DEFINE_CONN_EVENT(disconnect); ...@@ -415,7 +415,6 @@ DEFINE_CONN_EVENT(disconnect);
DEFINE_RXPRT_EVENT(xprtrdma_create); DEFINE_RXPRT_EVENT(xprtrdma_create);
DEFINE_RXPRT_EVENT(xprtrdma_op_destroy); DEFINE_RXPRT_EVENT(xprtrdma_op_destroy);
DEFINE_RXPRT_EVENT(xprtrdma_remove); DEFINE_RXPRT_EVENT(xprtrdma_remove);
DEFINE_RXPRT_EVENT(xprtrdma_reinsert);
DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc); DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc);
DEFINE_RXPRT_EVENT(xprtrdma_op_close); DEFINE_RXPRT_EVENT(xprtrdma_op_close);
DEFINE_RXPRT_EVENT(xprtrdma_op_setport); DEFINE_RXPRT_EVENT(xprtrdma_op_setport);
......
...@@ -286,7 +286,6 @@ xprt_rdma_destroy(struct rpc_xprt *xprt) ...@@ -286,7 +286,6 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
rpcrdma_xprt_disconnect(r_xprt); rpcrdma_xprt_disconnect(r_xprt);
rpcrdma_buffer_destroy(&r_xprt->rx_buf); rpcrdma_buffer_destroy(&r_xprt->rx_buf);
rpcrdma_ia_close(&r_xprt->rx_ia);
xprt_rdma_free_addresses(xprt); xprt_rdma_free_addresses(xprt);
xprt_free(xprt); xprt_free(xprt);
...@@ -347,10 +346,6 @@ xprt_setup_rdma(struct xprt_create *args) ...@@ -347,10 +346,6 @@ xprt_setup_rdma(struct xprt_create *args)
xprt_rdma_format_addresses(xprt, sap); xprt_rdma_format_addresses(xprt, sap);
new_xprt = rpcx_to_rdmax(xprt); new_xprt = rpcx_to_rdmax(xprt);
rc = rpcrdma_ia_open(new_xprt);
if (rc)
goto out1;
rc = rpcrdma_buffer_create(new_xprt); rc = rpcrdma_buffer_create(new_xprt);
if (rc) if (rc)
goto out2; goto out2;
...@@ -372,8 +367,6 @@ xprt_setup_rdma(struct xprt_create *args) ...@@ -372,8 +367,6 @@ xprt_setup_rdma(struct xprt_create *args)
rpcrdma_buffer_destroy(&new_xprt->rx_buf); rpcrdma_buffer_destroy(&new_xprt->rx_buf);
rc = -ENODEV; rc = -ENODEV;
out2: out2:
rpcrdma_ia_close(&new_xprt->rx_ia);
out1:
trace_xprtrdma_op_destroy(new_xprt); trace_xprtrdma_op_destroy(new_xprt);
xprt_rdma_free_addresses(xprt); xprt_rdma_free_addresses(xprt);
xprt_free(xprt); xprt_free(xprt);
......
...@@ -345,31 +345,6 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia) ...@@ -345,31 +345,6 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia)
* Exported functions. * Exported functions.
*/ */
/**
* rpcrdma_ia_open - Open and initialize an Interface Adapter.
* @xprt: transport with IA to (re)initialize
*
* Returns 0 on success, negative errno if an appropriate
* Interface Adapter could not be found and opened.
*/
int
rpcrdma_ia_open(struct rpcrdma_xprt *xprt)
{
struct rpcrdma_ia *ia = &xprt->rx_ia;
int rc;
ia->ri_id = rpcrdma_create_id(xprt, ia);
if (IS_ERR(ia->ri_id)) {
rc = PTR_ERR(ia->ri_id);
goto out_err;
}
return 0;
out_err:
rpcrdma_ia_close(ia);
return rc;
}
/** /**
* rpcrdma_ia_remove - Handle device driver unload * rpcrdma_ia_remove - Handle device driver unload
* @ia: interface adapter being removed * @ia: interface adapter being removed
...@@ -401,34 +376,26 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) ...@@ -401,34 +376,26 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
trace_xprtrdma_remove(r_xprt); trace_xprtrdma_remove(r_xprt);
} }
/** static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
* rpcrdma_ia_close - Clean up/close an IA.
* @ia: interface adapter to close
*
*/
void
rpcrdma_ia_close(struct rpcrdma_ia *ia)
{
if (ia->ri_id && !IS_ERR(ia->ri_id))
rdma_destroy_id(ia->ri_id);
ia->ri_id = NULL;
}
static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt,
struct rdma_cm_id *id)
{ {
struct rpcrdma_ep *ep = &r_xprt->rx_ep; struct rpcrdma_ep *ep = &r_xprt->rx_ep;
struct rpcrdma_ia *ia = &r_xprt->rx_ia; struct rpcrdma_ia *ia = &r_xprt->rx_ia;
struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private; struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
struct rdma_cm_id *id;
int rc; int rc;
id = rpcrdma_create_id(r_xprt, ia);
if (IS_ERR(id))
return PTR_ERR(id);
ep->rep_max_requests = r_xprt->rx_xprt.max_reqs; ep->rep_max_requests = r_xprt->rx_xprt.max_reqs;
ep->rep_inline_send = xprt_rdma_max_inline_write; ep->rep_inline_send = xprt_rdma_max_inline_write;
ep->rep_inline_recv = xprt_rdma_max_inline_read; ep->rep_inline_recv = xprt_rdma_max_inline_read;
rc = frwr_query_device(r_xprt, id->device); rc = frwr_query_device(r_xprt, id->device);
if (rc) if (rc)
return rc; goto out_destroy;
r_xprt->rx_buf.rb_max_requests = cpu_to_be32(ep->rep_max_requests); r_xprt->rx_buf.rb_max_requests = cpu_to_be32(ep->rep_max_requests);
ep->rep_attr.event_handler = rpcrdma_qp_event_handler; ep->rep_attr.event_handler = rpcrdma_qp_event_handler;
...@@ -507,10 +474,12 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt, ...@@ -507,10 +474,12 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt,
rc = rdma_create_qp(id, ia->ri_pd, &ep->rep_attr); rc = rdma_create_qp(id, ia->ri_pd, &ep->rep_attr);
if (rc) if (rc)
goto out_destroy; goto out_destroy;
ia->ri_id = id;
return 0; return 0;
out_destroy: out_destroy:
rpcrdma_ep_destroy(r_xprt); rpcrdma_ep_destroy(r_xprt);
rdma_destroy_id(id);
return rc; return rc;
} }
...@@ -536,79 +505,8 @@ static void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt) ...@@ -536,79 +505,8 @@ static void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt)
ia->ri_pd = NULL; ia->ri_pd = NULL;
} }
/* Re-establish a connection after a device removal event. /*
* Unlike a normal reconnection, a fresh PD and a new set * Connect unconnected endpoint.
* of MRs and buffers is needed.
*/
static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt)
{
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
int rc, err;
trace_xprtrdma_reinsert(r_xprt);
rc = -EHOSTUNREACH;
if (rpcrdma_ia_open(r_xprt))
goto out1;
rc = -ENETUNREACH;
err = rpcrdma_ep_create(r_xprt, ia->ri_id);
if (err)
goto out2;
return 0;
out2:
rpcrdma_ia_close(ia);
out1:
return rc;
}
static int rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt)
{
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
struct rdma_cm_id *id, *old;
int err, rc;
rc = -EHOSTUNREACH;
id = rpcrdma_create_id(r_xprt, ia);
if (IS_ERR(id))
goto out;
/* As long as the new ID points to the same device as the
* old ID, we can reuse the transport's existing PD and all
* previously allocated MRs. Also, the same device means
* the transport's previous DMA mappings are still valid.
*
* This is a sanity check only. There should be no way these
* point to two different devices here.
*/
old = id;
rc = -ENETUNREACH;
if (ia->ri_id->device != id->device) {
pr_err("rpcrdma: can't reconnect on different device!\n");
goto out_destroy;
}
err = rpcrdma_ep_create(r_xprt, id);
if (err)
goto out_destroy;
/* Atomically replace the transport's ID. */
rc = 0;
old = ia->ri_id;
ia->ri_id = id;
out_destroy:
rdma_destroy_id(old);
out:
return rc;
}
/**
* rpcrdma_xprt_connect - Connect an unconnected transport
* @r_xprt: controlling transport instance
*
* Returns 0 on success or a negative errno.
*/ */
int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt) int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
{ {
...@@ -618,25 +516,10 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt) ...@@ -618,25 +516,10 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
int rc; int rc;
retry: retry:
switch (ep->rep_connected) { rpcrdma_xprt_disconnect(r_xprt);
case 0: rc = rpcrdma_ep_create(r_xprt);
rc = -ENETUNREACH; if (rc)
if (rpcrdma_ep_create(r_xprt, ia->ri_id)) goto out_noupdate;
goto out_noupdate;
break;
case -ENODEV:
rc = rpcrdma_ep_recreate_xprt(r_xprt);
if (rc)
goto out_noupdate;
break;
case 1:
rpcrdma_xprt_disconnect(r_xprt);
/* fall through */
default:
rc = rpcrdma_ep_reconnect(r_xprt);
if (rc)
goto out;
}
ep->rep_connected = 0; ep->rep_connected = 0;
xprt_clear_connected(xprt); xprt_clear_connected(xprt);
...@@ -712,6 +595,10 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt) ...@@ -712,6 +595,10 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt)
rpcrdma_sendctxs_destroy(r_xprt); rpcrdma_sendctxs_destroy(r_xprt);
rpcrdma_ep_destroy(r_xprt); rpcrdma_ep_destroy(r_xprt);
if (ia->ri_id)
rdma_destroy_id(ia->ri_id);
ia->ri_id = NULL;
} }
/* Fixed-size circular FIFO queue. This implementation is wait-free and /* Fixed-size circular FIFO queue. This implementation is wait-free and
......
...@@ -457,9 +457,7 @@ extern unsigned int xprt_rdma_memreg_strategy; ...@@ -457,9 +457,7 @@ extern unsigned int xprt_rdma_memreg_strategy;
/* /*
* Interface Adapter calls - xprtrdma/verbs.c * Interface Adapter calls - xprtrdma/verbs.c
*/ */
int rpcrdma_ia_open(struct rpcrdma_xprt *xprt);
void rpcrdma_ia_remove(struct rpcrdma_ia *ia); void rpcrdma_ia_remove(struct rpcrdma_ia *ia);
void rpcrdma_ia_close(struct rpcrdma_ia *);
/* /*
* Endpoint calls - xprtrdma/verbs.c * Endpoint calls - xprtrdma/verbs.c
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment