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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -415,7 +415,6 @@ DEFINE_CONN_EVENT(disconnect);
DEFINE_RXPRT_EVENT(xprtrdma_create);
DEFINE_RXPRT_EVENT(xprtrdma_op_destroy);
DEFINE_RXPRT_EVENT(xprtrdma_remove);
DEFINE_RXPRT_EVENT(xprtrdma_reinsert);
DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc);
DEFINE_RXPRT_EVENT(xprtrdma_op_close);
DEFINE_RXPRT_EVENT(xprtrdma_op_setport);
+0 −7
Original line number Diff line number Diff line
@@ -286,7 +286,6 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)

	rpcrdma_xprt_disconnect(r_xprt);
	rpcrdma_buffer_destroy(&r_xprt->rx_buf);
	rpcrdma_ia_close(&r_xprt->rx_ia);

	xprt_rdma_free_addresses(xprt);
	xprt_free(xprt);
@@ -347,10 +346,6 @@ xprt_setup_rdma(struct xprt_create *args)
	xprt_rdma_format_addresses(xprt, sap);

	new_xprt = rpcx_to_rdmax(xprt);
	rc = rpcrdma_ia_open(new_xprt);
	if (rc)
		goto out1;

	rc = rpcrdma_buffer_create(new_xprt);
	if (rc)
		goto out2;
@@ -372,8 +367,6 @@ out4:
	rpcrdma_buffer_destroy(&new_xprt->rx_buf);
	rc = -ENODEV;
out2:
	rpcrdma_ia_close(&new_xprt->rx_ia);
out1:
	trace_xprtrdma_op_destroy(new_xprt);
	xprt_rdma_free_addresses(xprt);
	xprt_free(xprt);
+20 −133
Original line number Diff line number Diff line
@@ -345,31 +345,6 @@ out:
 * 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
 * @ia: interface adapter being removed
@@ -401,34 +376,26 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
	trace_xprtrdma_remove(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)
static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
{
	struct rpcrdma_ep *ep = &r_xprt->rx_ep;
	struct rpcrdma_ia *ia = &r_xprt->rx_ia;
	struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
	struct rdma_cm_id *id;
	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_inline_send = xprt_rdma_max_inline_write;
	ep->rep_inline_recv = xprt_rdma_max_inline_read;

	rc = frwr_query_device(r_xprt, id->device);
	if (rc)
		return rc;
		goto out_destroy;

	r_xprt->rx_buf.rb_max_requests = cpu_to_be32(ep->rep_max_requests);

	ep->rep_attr.event_handler = rpcrdma_qp_event_handler;
@@ -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);
	if (rc)
		goto out_destroy;
	ia->ri_id = id;
	return 0;

out_destroy:
	rpcrdma_ep_destroy(r_xprt);
	rdma_destroy_id(id);
	return rc;
}

@@ -536,79 +505,8 @@ static void rpcrdma_ep_destroy(struct rpcrdma_xprt *r_xprt)
	ia->ri_pd = NULL;
}

/* Re-establish a connection after a device removal event.
 * Unlike a normal reconnection, a fresh PD and a new set
 * 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.
/*
 * Connect unconnected endpoint.
 */
int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
{
@@ -618,25 +516,10 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
	int rc;

retry:
	switch (ep->rep_connected) {
	case 0:
		rc = -ENETUNREACH;
		if (rpcrdma_ep_create(r_xprt, ia->ri_id))
			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);
	rc = rpcrdma_ep_create(r_xprt);
	if (rc)
			goto out;
	}
		goto out_noupdate;

	ep->rep_connected = 0;
	xprt_clear_connected(xprt);
@@ -712,6 +595,10 @@ out:
	rpcrdma_sendctxs_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
+0 −2
Original line number Diff line number Diff line
@@ -457,9 +457,7 @@ extern unsigned int xprt_rdma_memreg_strategy;
/*
 * 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_close(struct rpcrdma_ia *);

/*
 * Endpoint calls - xprtrdma/verbs.c