Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fee08caf authored by Tom Talpey's avatar Tom Talpey Committed by Trond Myklebust
Browse files

RPC/RDMA: avoid an oops due to disconnect racing with async upcalls.



RDMA disconnects yield an upcall from the RDMA connection manager,
which can race with rpc transport close, e.g. on ^C of a mount.
Ensure any rdma cm_id and qp are fully destroyed before continuing.

Signed-off-by: default avatarTom Talpey <talpey@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent ad0e9e01
Loading
Loading
Loading
Loading
+9 −11
Original line number Original line Diff line number Diff line
@@ -565,6 +565,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
	return 0;
	return 0;
out2:
out2:
	rdma_destroy_id(ia->ri_id);
	rdma_destroy_id(ia->ri_id);
	ia->ri_id = NULL;
out1:
out1:
	return rc;
	return rc;
}
}
@@ -585,15 +586,17 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
		dprintk("RPC:       %s: ib_dereg_mr returned %i\n",
		dprintk("RPC:       %s: ib_dereg_mr returned %i\n",
			__func__, rc);
			__func__, rc);
	}
	}
	if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp)
	if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) {
		if (ia->ri_id->qp)
			rdma_destroy_qp(ia->ri_id);
			rdma_destroy_qp(ia->ri_id);
		rdma_destroy_id(ia->ri_id);
		ia->ri_id = NULL;
	}
	if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) {
	if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) {
		rc = ib_dealloc_pd(ia->ri_pd);
		rc = ib_dealloc_pd(ia->ri_pd);
		dprintk("RPC:       %s: ib_dealloc_pd returned %i\n",
		dprintk("RPC:       %s: ib_dealloc_pd returned %i\n",
			__func__, rc);
			__func__, rc);
	}
	}
	if (ia->ri_id != NULL && !IS_ERR(ia->ri_id))
		rdma_destroy_id(ia->ri_id);
}
}


/*
/*
@@ -751,21 +754,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
		if (rc)
		if (rc)
			dprintk("RPC:       %s: rpcrdma_ep_disconnect"
			dprintk("RPC:       %s: rpcrdma_ep_disconnect"
				" returned %i\n", __func__, rc);
				" returned %i\n", __func__, rc);
		rdma_destroy_qp(ia->ri_id);
		ia->ri_id->qp = NULL;
	}
	}


	ep->rep_func = NULL;

	/* padding - could be done in rpcrdma_buffer_destroy... */
	/* padding - could be done in rpcrdma_buffer_destroy... */
	if (ep->rep_pad_mr) {
	if (ep->rep_pad_mr) {
		rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad);
		rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad);
		ep->rep_pad_mr = NULL;
		ep->rep_pad_mr = NULL;
	}
	}


	if (ia->ri_id->qp) {
		rdma_destroy_qp(ia->ri_id);
		ia->ri_id->qp = NULL;
	}

	rpcrdma_clean_cq(ep->rep_cq);
	rpcrdma_clean_cq(ep->rep_cq);
	rc = ib_destroy_cq(ep->rep_cq);
	rc = ib_destroy_cq(ep->rep_cq);
	if (rc)
	if (rc)